PluginProbe ʕ •ᴥ•ʔ
Responsive Lightbox & Gallery / trunk
Responsive Lightbox & Gallery vtrunk
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 1 week ago providers 4 months ago settings 4 months ago class-fast-image.php 2 years ago class-folders.php 1 week ago class-frontend.php 1 week ago class-galleries.php 4 months ago class-multilang.php 2 years ago class-remote-library-api.php 1 week ago class-remote-library.php 1 week ago class-settings-api.php 1 month ago class-settings-data.php 5 months ago class-settings-pages.php 4 months ago class-settings.php 4 months ago class-tour.php 5 months ago class-welcome.php 4 months ago class-widgets.php 2 years ago functions.php 3 years ago
class-galleries.php
1858 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 $design = is_array( $design ) ? $design : [];
490
491 if ( ! empty( $design['menu_item'] ) && isset( $design[$design['menu_item']] ) && is_array( $design[$design['menu_item']] ) ) {
492 $design_data = $design[$design['menu_item']];
493
494 // remove show_title to avoid shortcode attribute duplication
495 if ( isset( $design_data['show_title'] ) ) {
496 if ( ! isset( $design_data['design_show_title'] ) )
497 $design_data['design_show_title'] = $design_data['show_title'];
498
499 unset( $design_data['show_title'] );
500 }
501
502 // remove show_caption to avoid shortcode attribute duplication
503 if ( isset( $design_data['show_caption'] ) ) {
504 if ( ! isset( $design_data['design_show_caption'] ) )
505 $design_data['design_show_caption'] = $design_data['show_caption'];
506
507 unset( $design_data['show_caption'] );
508 }
509
510 foreach ( $design_data as $arg => $value ) {
511 $shortcode .= ' ' . esc_attr( $arg ) . '="' . esc_attr( (string) $value ) . '"';
512 }
513 }
514
515 // get lightbox data
516 $lightbox = get_post_meta( $args['id'], '_rl_lightbox', true );
517 $lightbox = is_array( $lightbox ) ? $lightbox : [];
518
519 if ( ! empty( $lightbox['menu_item'] ) && isset( $lightbox[$lightbox['menu_item']] ) && is_array( $lightbox[$lightbox['menu_item']] ) ) {
520 foreach ( $lightbox[$lightbox['menu_item']] as $arg => $value ) {
521 $shortcode .= ' ' . esc_attr( $arg ) . '="' . esc_attr( (string) $value ) . '"';
522 }
523 }
524
525 $forced_gallery_no = 0;
526
527 // check forced gallery number
528 if ( isset( $args['gallery_no'] ) ) {
529 $args['gallery_no'] = (int) $args['gallery_no'];
530
531 if ( $args['gallery_no'] > 0 )
532 $forced_gallery_no = $args['gallery_no'];
533 }
534
535 // get content
536 $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 . ']' );
537
538 // make sure every filter is available in frontend ajax
539 if ( wp_doing_ajax() )
540 $content = $rl->frontend->add_lightbox( $content );
541
542 return $content;
543 }
544
545 /**
546 * Add a gallery button.
547 *
548 * @param string $editor_id Editor ID
549 * @return void
550 */
551 public function add_gallery_button( $editor_id ) {
552 if ( get_post_type() === 'rl_gallery' )
553 return;
554
555 $this->enqueue_gallery_scripts_styles();
556
557 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>';
558 }
559
560 /**
561 * Enqueue scripts and styles needed for gallery modal.
562 *
563 * @global string $pagenow
564 *
565 * @return void
566 */
567 public function enqueue_gallery_scripts_styles() {
568 global $pagenow;
569
570 // count how many times function was executed
571 static $run = 0;
572
573 // allow this only once
574 if ( $run > 0 )
575 return;
576
577 $run++;
578
579 // get main instance
580 $rl = Responsive_Lightbox();
581
582 wp_enqueue_script( 'responsive-lightbox-admin-gallery', RESPONSIVE_LIGHTBOX_URL . '/js/admin-gallery.js', array( 'jquery', 'underscore' ), $rl->defaults['version'], false );
583
584 // prepare script data
585 $script_data = [
586 'nonce' => wp_create_nonce( 'rl-gallery-post' ),
587 'post_id' => get_the_ID(),
588 'page' => esc_url( $pagenow )
589 ];
590
591 wp_add_inline_script( 'responsive-lightbox-admin-gallery', 'var rlArgsGallery = ' . wp_json_encode( $script_data ) . ";\n", 'before' );
592
593 wp_enqueue_style( 'responsive-lightbox-admin-gallery', RESPONSIVE_LIGHTBOX_URL . '/css/admin-gallery.css', [], $rl->defaults['version'] );
594 }
595
596 /**
597 * Modal gallery HTML template.
598 *
599 * @global string $wp_version
600 * @global string $pagenow
601 *
602 * @return void
603 */
604 public function modal_gallery_template() {
605 global $wp_version;
606 global $pagenow;
607
608 // display only for post edit pages
609 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' ) ) ) )
610 return;
611
612 // get main instance
613 $rl = Responsive_Lightbox();
614
615 $categories = '';
616
617 // builder categories?
618 if ( $rl->options['builder']['categories'] ) {
619 $terms = get_terms(
620 array(
621 'taxonomy' => 'rl_category',
622 'orderby' => 'name',
623 'order' => 'ASC',
624 'hide_empty' => false,
625 'fields' => 'id=>name'
626 )
627 );
628
629 // get categories dropdown
630 $categories = wp_dropdown_categories(
631 array(
632 'orderby' => 'name',
633 'order' => 'asc',
634 'show_option_none' => empty( $terms ) ? __( 'All categories', 'responsive-lightbox' ) : '',
635 'show_option_all' => __( 'All categories', 'responsive-lightbox' ),
636 'show_count' => false,
637 'hide_empty' => false,
638 'option_none_value' => 0,
639 'hierarchical' => true,
640 'selected' => 0,
641 'taxonomy' => 'rl_category',
642 'hide_if_empty' => false,
643 'echo' => false,
644 'id' => 'rl-media-attachment-categories',
645 'class' => 'attachment-filters',
646 'name' => ''
647 )
648 );
649 }
650
651 echo '
652 <div id="rl-modal-gallery" style="display: none;">
653 <div class="media-modal wp-core-ui">
654 <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>
655 <div class="media-modal-content">
656 <div class="media-frame mode-select wp-core-ui hide-menu hide-router">
657 <div class="media-frame-title">
658 <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>
659 </div>
660 <div class="media-frame-content" data-columns="0">
661 <div class="attachments-browser">
662 <div class="uploader-inline rl-no-galleries" style="display: none;">
663 <div class="uploader-inline-content has-upload-message">
664 <h2 class="upload-message">' . esc_html__( 'No items found.', 'responsive-lightbox' ) . '</h2>
665 <div class="upload-ui">
666 <h2 class="upload-instructions">' . esc_html__( 'No galleries? Create them first or try another search phrase.', 'responsive-lightbox' ) . '</h2>
667 </div>
668 </div>
669 </div>
670 <div class="media-toolbar">' . ( $rl->options['builder']['categories'] ? '
671 <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>' : '' ) . '
672 <div class="media-toolbar-primary search-form">
673 <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">
674 </div>
675 </div>
676 <ul class="attachments rl-galleries-list ui-sortable ui-sortable-disabled">
677 </ul>
678 <div class="media-sidebar visible">
679 <h2>' . esc_html__( 'Select A Gallery', 'responsive-lightbox' ) . '</h2>
680 <p>' . esc_html__( 'To select a gallery simply click on one of the boxes to the left.', 'responsive-lightbox' ) . '</p>
681 <p>' . esc_html__( 'To insert your gallery into the editor, click on the "Insert Gallery" button below.', 'responsive-lightbox' ) . '</p>
682 </div>
683 </div>
684 </div>
685 <div class="media-frame-toolbar">
686 <div class="media-toolbar">
687 <div class="media-toolbar-secondary">
688 <div class="media-selection empty">
689 <div class="selection-info">
690 <span class="rl-gallery-count count">' . esc_html( sprintf( _n( '%s image', '%s images', 0, 'responsive-lightbox' ), 0 ) ) . '</span>
691 <a href="" class="button-link rl-edit-gallery-link">' . esc_html__( 'Edit gallery', 'responsive-lightbox' ) . '</a>
692 </div>
693 <div class="selection-view">
694 <span class="rl-gallery-images-spinner spinner" style="display: none;"></span>
695 <ul class="attachments rl-attachments-list">
696 </ul>
697 </div>
698 </div>
699 </div>
700 <div class="media-toolbar-primary search-form">
701 <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>
702 <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>
703 <button type="button" class="button media-button button-secondary button-large rl-media-button-cancel-gallery">' . esc_html__( 'Cancel', 'responsive-lightbox') . '</button>
704 </div>
705 </div>
706 </div>
707 </div>
708 </div>
709 </div>
710 <div class="media-modal-backdrop"></div>
711 </div>';
712 }
713
714 /**
715 * Add menu tabs after the post title.
716 *
717 * @global array $wp_meta_boxes
718 *
719 * @param object $post Post object
720 * @return void
721 */
722 public function after_title_nav_menu( $post ) {
723 if ( $post->post_type !== 'rl_gallery' )
724 return;
725
726 global $wp_meta_boxes;
727
728 // check active tab
729 $active_tab = isset( $_GET['rl_active_tab'] ) ? sanitize_key( $_GET['rl_active_tab'] ) : '';
730 $active_tab = ! empty( $active_tab ) && array_key_exists( $active_tab, $this->tabs ) ? $active_tab : 'images';
731
732 echo '
733 <div class="rl-settings-wrapper">
734 <h2 class="nav-tab-wrapper">';
735
736 foreach ( $this->tabs as $key => $data ) {
737 echo '
738 <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>';
739 }
740
741 echo '
742 </h2>';
743
744 do_meta_boxes( $post->post_type, 'responsive_lightbox_metaboxes', $post );
745
746 echo '
747 </div>';
748
749 unset( $wp_meta_boxes[$post->post_type]['responsive_lightbox_metaboxes'] );
750 }
751
752 /**
753 * Add class to hide metabox.
754 *
755 * @param array $classes
756 * @return array
757 */
758 public function hide_metabox( $classes ) {
759 $classes[] = 'rl-metabox-content';
760 $classes[] = 'rl-hide-metabox';
761
762 return $classes;
763 }
764
765 /**
766 * Add class to display the metabox.
767 *
768 * @param array $classes
769 * @return array
770 */
771 function display_metabox( $classes ) {
772 $classes[] = 'rl-metabox-content';
773 $classes[] = 'rl-display-metabox';
774
775 return $classes;
776 }
777
778 /**
779 * Add settings wrapper class to the metabox.
780 *
781 * @param array $classes
782 * @return array
783 */
784 public function add_settings_wrapper_class( $classes ) {
785 if ( ! in_array( 'rl-settings', $classes, true ) )
786 $classes[] = 'rl-settings';
787
788 return $classes;
789 }
790
791 /**
792 * Add active tab to post redirect destination URL.
793 *
794 * @param string $location Destination URL
795 * @return string
796 */
797 function add_active_tab( $location ) {
798 // check active tab
799 $active_tab = isset( $_POST['rl_active_tab'] ) ? sanitize_key( $_POST['rl_active_tab'] ) : '';
800
801 return add_query_arg( 'rl_active_tab', ! empty( $active_tab ) && array_key_exists( $active_tab, $this->tabs ) ? $active_tab : 'images', $location );
802 }
803
804 /**
805 * Add metaboxes.
806 *
807 * @return void
808 */
809 public function add_meta_boxes() {
810 // side metaboxes
811 add_meta_box( 'responsive-gallery-shortcode', esc_html__( 'Gallery Code', 'responsive-lightbox' ), array( $this, 'shortcode_metabox' ), 'rl_gallery', 'side', 'core' );
812 }
813
814 /**
815 * Get number of gallery images.
816 *
817 * @param int $gallery_id
818 * @return int
819 */
820 public function get_gallery_images_number( $gallery_id ) {
821 return count( $this->get_gallery_images( $gallery_id, [ 'count_images' => true, 'preview' => false, 'exclude' => true ] ) );
822 }
823
824 /**
825 * Sync gallery image counts when an attachment is deleted.
826 *
827 * @param int $attachment_id
828 * @return void
829 */
830 public function delete_attachment( $attachment_id ) {
831 $attachment_id = (int) $attachment_id;
832 if ( $attachment_id <= 0 )
833 return;
834
835 $galleries = get_posts( [
836 'post_type' => 'rl_gallery',
837 'post_status' => [ 'publish', 'private', 'draft', 'pending', 'future' ],
838 'fields' => 'ids',
839 'nopaging' => true,
840 'meta_query' => [
841 [
842 'key' => '_rl_images',
843 'value' => (string) $attachment_id,
844 'compare' => 'LIKE'
845 ]
846 ]
847 ] );
848
849 if ( empty( $galleries ) )
850 return;
851
852 foreach ( $galleries as $gallery_id ) {
853 update_post_meta( $gallery_id, '_rl_images_count', $this->get_gallery_images_number( $gallery_id ) );
854 }
855 }
856
857 /**
858 * Load featured content query args.
859 *
860 * @global string $pagenow
861 *
862 * @return void
863 */
864 public function init_admin() {
865 global $pagenow;
866
867 // check values
868 $post = isset( $_GET['post'] ) ? (int) $_GET['post'] : 0;
869 $post_id = isset( $_POST['post_ID'] ) ? (int) $_POST['post_ID'] : 0;
870 $action = isset( $_POST['action'] ) ? sanitize_key( $_POST['action'] ) : '';
871 $post_type = isset( $_POST['post_type'] ) ? sanitize_key( $_POST['post_type'] ) : '';
872
873 // prepare query arguments if needed
874 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 ) ) )
875 $this->fields['images']['featured'] = $this->prepare_featured_fields( $this->fields['images']['featured'] );
876
877 // add default thumbnail image if needed
878 if ( Responsive_Lightbox()->options['builder']['gallery_builder'] && $pagenow === 'edit.php' && $post_type && $post_type === 'rl_gallery' )
879 $this->maybe_generate_thumbnail();
880 }
881
882 /**
883 * Generate post thumbnail replacement.
884 *
885 * @return int
886 */
887 public function maybe_generate_thumbnail() {
888 // get old attachment
889 $thumbnail_id = get_posts(
890 array(
891 'name' => 'responsive-lightbox-thumbnail',
892 'post_type' => 'attachment',
893 'post_status' => 'inherit',
894 'numberposts' => 1,
895 'fields' => 'ids'
896 )
897 );
898
899 // no attachment?
900 if ( empty( $thumbnail_id ) ) {
901 // get new attachment
902 $thumbnail_id = get_posts(
903 array(
904 'name' => 'responsive-lightbox-thumbnail',
905 'post_type' => 'attachment',
906 'post_status' => 'pending',
907 'numberposts' => 1,
908 'fields' => 'ids'
909 )
910 );
911
912 // no attachment?
913 if ( empty( $thumbnail_id ) ) {
914 // get upload directory data
915 $wp_upload_dir = wp_upload_dir();
916
917 // get file path
918 $filepath = str_replace( '\\', '/', RESPONSIVE_LIGHTBOX_PATH . 'images/responsive-lightbox-thumbnail.png' );
919
920 // get file name
921 $filename = basename( $filepath );
922
923 // new filepath in upload dir
924 $new_filepath = $wp_upload_dir['path'] . '/' . $filename;
925
926 // copty file to upload dir
927 copy( $filepath, $new_filepath );
928
929 // get type of file
930 $filetype = wp_check_filetype( $filename );
931
932 // force pending status for the attachment
933 add_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
934
935 // insert attachment
936 $thumbnail_id = wp_insert_attachment(
937 array(
938 'guid' => $wp_upload_dir['url'] . '/' . $filename,
939 'post_mime_type' => $filetype['type'],
940 'post_title' => preg_replace( '/\.[^.]+$/', '', $filename ),
941 'post_content' => '',
942 'post_parent' => 0,
943 'post_status' => 'inherit'
944 ),
945 $new_filepath,
946 0
947 );
948
949 remove_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
950
951 // success?
952 if ( $thumbnail_id ) {
953 // make sure that this file is included
954 require_once( ABSPATH . 'wp-admin/includes/image.php' );
955
956 // update database with generated metadata for the attachment
957 wp_update_attachment_metadata( $thumbnail_id, wp_generate_attachment_metadata( $thumbnail_id, $new_filepath ) );
958 }
959 } else
960 $thumbnail_id = $thumbnail_id[0];
961 } else {
962 // force pending status for the attachment
963 add_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
964
965 $thumbnail_id = wp_update_post(
966 array(
967 'ID' => $thumbnail_id[0],
968 'post_status' => 'pending'
969 )
970 );
971
972 remove_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
973 }
974
975 return (int) $thumbnail_id;
976 }
977
978 /**
979 * Get video thumbnail replacement.
980 *
981 * @param int $post_id
982 * @return int
983 */
984 public function get_video_thumbnail_id( $post_id ) {
985 $thumbnail_id = 0;
986
987 // try to get video thumbnail
988 $attachment_id = (int) get_post_thumbnail_id( $post_id );
989
990 // real attachment?
991 if ( wp_attachment_is_image( $attachment_id ) )
992 $thumbnail_id = $attachment_id;
993
994 // try to get default video poster image
995 if ( ! $thumbnail_id ) {
996 $thumbnail_id = get_posts(
997 array(
998 'name' => 'responsive-lightbox-video-thumbnail',
999 'post_type' => 'attachment',
1000 'post_status' => 'inherit',
1001 'numberposts' => 1,
1002 'fields' => 'ids'
1003 )
1004 );
1005 }
1006
1007 // no attachment?
1008 if ( ! $thumbnail_id ) {
1009 // get new attachment
1010 $thumbnail_id = get_posts(
1011 array(
1012 'name' => 'responsive-lightbox-video-thumbnail',
1013 'post_type' => 'attachment',
1014 'post_status' => 'pending',
1015 'numberposts' => 1,
1016 'fields' => 'ids'
1017 )
1018 );
1019
1020 // no attachment?
1021 if ( ! $thumbnail_id ) {
1022 // get upload directory data
1023 $wp_upload_dir = wp_upload_dir();
1024
1025 // get file path
1026 $filepath = str_replace( '\\', '/', RESPONSIVE_LIGHTBOX_PATH . 'images/responsive-lightbox-video-thumbnail.png' );
1027
1028 // get file name
1029 $filename = basename( $filepath );
1030
1031 // new filepath in upload dir
1032 $new_filepath = $wp_upload_dir['path'] . '/' . $filename;
1033
1034 // copty file to upload dir
1035 copy( $filepath, $new_filepath );
1036
1037 // get type of file
1038 $filetype = wp_check_filetype( $filename );
1039
1040 // force pending status for the attachment
1041 add_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
1042
1043 // insert attachment
1044 $thumbnail_id = wp_insert_attachment(
1045 array(
1046 'guid' => $wp_upload_dir['url'] . '/' . $filename,
1047 'post_mime_type' => $filetype['type'],
1048 'post_title' => preg_replace( '/\.[^.]+$/', '', $filename ),
1049 'post_content' => '',
1050 'post_parent' => 0,
1051 'post_status' => 'inherit'
1052 ),
1053 $new_filepath,
1054 0
1055 );
1056
1057 remove_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
1058
1059 // success?
1060 if ( $thumbnail_id ) {
1061 // make sure that this file is included
1062 require_once( ABSPATH . 'wp-admin/includes/image.php' );
1063
1064 // update database with generated metadata for the attachment
1065 wp_update_attachment_metadata( $thumbnail_id, wp_generate_attachment_metadata( $thumbnail_id, $new_filepath ) );
1066 }
1067 } else
1068 $thumbnail_id = $thumbnail_id[0];
1069 }
1070
1071 return (int) $thumbnail_id;
1072 }
1073
1074 /**
1075 * Change status of new attachment thumbnail replacement.
1076 *
1077 * @param array $data
1078 * @return array
1079 */
1080 function set_attachment_post_status( $data ) {
1081 $data['post_status'] = 'pending';
1082
1083 return $data;
1084 }
1085
1086 /**
1087 * Prepare featured content fields.
1088 *
1089 * @param array $fields
1090 * @return array
1091 */
1092 public function prepare_featured_fields( $fields ) {
1093 foreach ( array( 'post_type', 'post_status', 'post_format', 'post_term', 'post_author', 'page_parent', 'page_template' ) as $option ) {
1094 $fields[$option]['options'] = $this->prepare_query_args( $option );
1095 }
1096
1097 return $fields;
1098 }
1099
1100 /**
1101 * Prepare values option list.
1102 *
1103 * @param string $type
1104 * @return array
1105 */
1106 public function prepare_query_args( $type = '' ) {
1107 $html = '';
1108
1109 switch( $type ) {
1110 case 'post_type':
1111 $data = $this->get_post_types();
1112 break;
1113
1114 case 'post_status':
1115 $data = $this->get_post_statuses();
1116 break;
1117
1118 case 'post_format':
1119 $data = $this->get_post_formats();
1120 break;
1121
1122 case 'post_term':
1123 $taxonomies = $this->get_taxonomies();
1124 $new_terms = [];
1125
1126 if ( ! empty( $taxonomies ) ) {
1127 foreach ( $taxonomies as $tax_id => $label ) {
1128 $terms = get_terms(
1129 array(
1130 'taxonomy' => $tax_id,
1131 'orderby' => 'name',
1132 'order' => 'ASC',
1133 'hide_empty' => false,
1134 'fields' => 'id=>name'
1135 )
1136 );
1137
1138 if ( ! empty( $terms ) )
1139 $new_terms[$tax_id] = array(
1140 'label' => $label,
1141 'terms' => $terms
1142 );
1143 }
1144 }
1145
1146 $data = $new_terms;
1147 break;
1148
1149 case 'post_author':
1150 $data = $this->get_users();
1151 break;
1152
1153 case 'page_parent':
1154 $parents = [];
1155 $hierarchical = get_post_types(
1156 array(
1157 'public' => true,
1158 'hierarchical' => true
1159 ),
1160 'objects',
1161 'and'
1162 );
1163
1164 if ( ! empty( $hierarchical ) ) {
1165 foreach ( $hierarchical as $post_type => $object ) {
1166 // get top level hierarchical posts
1167 $query = new WP_Query(
1168 array(
1169 'post_type' => $post_type,
1170 'post_status' => 'publish',
1171 'nopaging' => true,
1172 'posts_per_page' => -1,
1173 'orderby' => 'title',
1174 'order' => 'ASC',
1175 'suppress_filters' => false,
1176 'no_found_rows' => true,
1177 'cache_results' => false,
1178 'post_parent' => 0
1179 )
1180 );
1181
1182 if ( ! empty( $query->posts ) ) {
1183 foreach ( $query->posts as $post ) {
1184 $parents[$post->ID] = trim( $post->post_title ) === '' ? __( 'Untitled' ) : $post->post_title;
1185 }
1186 }
1187 }
1188 }
1189
1190 $data = $parents;
1191 break;
1192
1193 case 'page_template':
1194 $data = $this->get_page_templates();
1195 break;
1196
1197 default:
1198 $data = [];
1199 }
1200
1201 return apply_filters( 'rl_galleries_prepare_query_args', $data, $type );
1202 }
1203
1204 /**
1205 * Get public post types.
1206 *
1207 * @param bool $simple Which data should be returned
1208 * @param bool $skip Which post types should be skipped
1209 * @return array
1210 */
1211 public function get_post_types( $simple = false, $skip = [ 'attachment', 'rl_gallery' ] ) {
1212 $post_types = get_post_types(
1213 array(
1214 'public' => true
1215 ),
1216 'objects',
1217 'and'
1218 );
1219
1220 $data = [];
1221
1222 if ( ! empty( $post_types ) ) {
1223 foreach ( $post_types as $post_type => $cpt ) {
1224 // skip unwanted post types
1225 if ( in_array( $post_type, $skip, true ) )
1226 continue;
1227
1228 if ( $simple )
1229 $data[] = $post_type;
1230 else
1231 $data[$post_type] = $cpt->labels->singular_name;
1232 }
1233 }
1234
1235 if ( ! $simple )
1236 asort( $data );
1237
1238 return $data;
1239 }
1240
1241 /**
1242 * Get post statuses.
1243 *
1244 * @return array
1245 */
1246 public function get_post_statuses() {
1247 $post_statuses = get_post_stati();
1248
1249 asort( $post_statuses );
1250
1251 // remove inherit post status
1252 if ( isset( $post_statuses['inherit'] ) )
1253 unset( $post_statuses['inherit'] );
1254
1255 return $post_statuses;
1256 }
1257
1258 /**
1259 * Get post formats.
1260 *
1261 * @return array
1262 */
1263 public function get_post_formats() {
1264 $post_formats = array(
1265 'aside' => __( 'Aside' ),
1266 'audio' => __( 'Audio' ),
1267 'chat' => __( 'Chat' ),
1268 'gallery' => __( 'Gallery' ),
1269 'link' => __( 'Link' ),
1270 'photo' => __( 'Photo' ),
1271 'quote' => __( 'Quote' ),
1272 'standard' => __( 'Standard' ),
1273 'status' => __( 'Status' ),
1274 'video' => __( 'Video' )
1275 );
1276
1277 asort( $post_formats );
1278
1279 return $post_formats;
1280 }
1281
1282 /**
1283 * Get taxonomies.
1284 *
1285 * @return array
1286 */
1287 public function get_taxonomies() {
1288 $taxonomies = get_taxonomies(
1289 array(
1290 'public' => true
1291 ),
1292 'objects',
1293 'and'
1294 );
1295
1296 // remove post format
1297 if ( array_key_exists( 'post_format', $taxonomies ) )
1298 unset( $taxonomies['post_format'] );
1299
1300 // get main instance
1301 $rl = Responsive_Lightbox();
1302
1303 // remove gallery categories
1304 if ( $rl->options['builder']['categories'] && array_key_exists( 'rl_category', $taxonomies ) )
1305 unset( $taxonomies['rl_category'] );
1306
1307 // remove gallery tags
1308 if ( $rl->options['builder']['tags'] && array_key_exists( 'rl_tag', $taxonomies ) )
1309 unset( $taxonomies['rl_tag'] );
1310
1311 if ( $rl->options['folders']['active'] ) {
1312 // remove active folders taxonomy from gallery source selector
1313 $active_taxonomy = $rl->folders->get_active_taxonomy();
1314 unset( $taxonomies[$active_taxonomy] );
1315
1316 // remove media folders tags
1317 if ( $rl->options['folders']['media_tags'] )
1318 unset( $taxonomies['rl_media_tag'] );
1319 }
1320
1321 $data = [];
1322
1323 if ( ! empty( $taxonomies ) ) {
1324 foreach ( $taxonomies as $tax_id => $taxonomy ) {
1325 $data[$tax_id] = $taxonomy->labels->singular_name;
1326 }
1327 }
1328
1329 // sort taxonomies
1330 asort( $data );
1331
1332 return $data;
1333 }
1334
1335 /**
1336 * Get users.
1337 *
1338 * @return array
1339 */
1340 public function get_users() {
1341 $users = get_users(
1342 array(
1343 'fields' => array( 'ID', 'user_login' )
1344 )
1345 );
1346
1347 $data = [];
1348
1349 if ( ! empty( $users ) ) {
1350 foreach ( $users as $user ) {
1351 $data[(int) $user->ID] = $user->user_login;
1352 }
1353 }
1354
1355 asort( $data );
1356
1357 return $data;
1358 }
1359
1360 /**
1361 * Get page templates.
1362 *
1363 * @return array
1364 */
1365 public function get_page_templates() {
1366 $data = [];
1367 $page_templates = wp_get_theme()->get_page_templates();
1368
1369 if ( ! empty( $page_templates ) )
1370 asort( $page_templates );
1371
1372 $data = array_merge( array( 'default' => apply_filters( 'default_page_template_title', __( 'Default Template' ) ) ), $page_templates );
1373
1374 return $data;
1375 }
1376
1377 /**
1378 * Fix possible misplaced or hidden metaboxes do to old 'after_title' metabox and possibility to move internal metaboxes.
1379 *
1380 * @return void
1381 */
1382 public function clear_metaboxes( $screen ) {
1383 global $pagenow;
1384
1385 if ( ! ( ( $pagenow === 'post.php' || $pagenow === 'post-new.php' ) && ! empty( $screen->post_type ) && $screen->post_type === 'rl_gallery' && empty( $_POST['rl_gallery'] ) ) )
1386 return;
1387
1388 // get user id
1389 $user_id = get_current_user_id();
1390
1391 // get rl metaboxes
1392 $order = get_user_meta( $user_id, 'meta-box-order_rl_gallery', true );
1393
1394 // any metabox order? fix possible misplaced metaboxes
1395 if ( is_array( $order ) && ! empty( $order ) ) {
1396 // save metaboxes
1397 $_order = $order;
1398
1399 // default rl metaboxes
1400 $rl_boxes = [ 'responsive-gallery-images', 'responsive-gallery-config', 'responsive-gallery-design', 'responsive-gallery-paging', 'responsive-gallery-lightbox', 'responsive-gallery-misc' ];
1401
1402 foreach ( $_order as $group => $metaboxes ) {
1403 if ( $group === 'after_title' ) {
1404 // remove deprecated after_title metabox
1405 unset( $order['after_title'] );
1406 } elseif ( $metaboxes !== '' ) {
1407 $boxes = explode( ',', $metaboxes );
1408 $new_boxes = [];
1409
1410 foreach ( $boxes as $box ) {
1411 if ( ! in_array( $box, $rl_boxes, true ) )
1412 $new_boxes[] = $box;
1413 }
1414
1415 if ( ! empty( $new_boxes ) )
1416 $order[$group] = implode( ',', $new_boxes );
1417 else
1418 $order[$group] = '';
1419 }
1420 }
1421
1422 // remove default metaboxes storage
1423 if ( array_key_exists( 'responsive_lightbox_metaboxes', $order ) )
1424 unset( $order['responsive_lightbox_metaboxes'] );
1425
1426 // update usermeta to prevent issues with rl metaboxes
1427 if ( $order !== $_order )
1428 update_user_meta( $user_id, 'meta-box-order_rl_gallery', $order );
1429 }
1430 }
1431
1432 /**
1433 * Save gallery metadata.
1434 *
1435 * @param int $post_id
1436 * @param object $post
1437 * @param bool $update Whether existing post is being updated or not
1438 * @return void
1439 */
1440 public function save_post( $post_id, $post, $update ) {
1441 // check action
1442 $action = isset( $_GET['action'] ) ? sanitize_key( $_GET['action'] ) : '';
1443
1444 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'] ) )
1445 return;
1446
1447 // save gallery
1448 $this->save_gallery( wp_unslash( $_POST ), $post_id );
1449 }
1450
1451 /**
1452 * Save gallery preview metadata.
1453 *
1454 * @param array $post_data Gallery data
1455 * @param int $post_id
1456 * @param bool $preview Whether is it preview
1457 * @return void
1458 */
1459 public function save_gallery( $post_data, $post_id, $preview = false ) {
1460 // get gallery data
1461 $data = $post_data['rl_gallery'];
1462
1463 // prepare sanitized data
1464 $safedata = [];
1465
1466 // get main instance
1467 $rl = Responsive_Lightbox();
1468
1469 // sanitize all fields - iterate from $this->tabs (authoritative registry) to prevent silent skipping
1470 foreach ( array_keys( $this->tabs ) as $tab_id ) {
1471 // Retrieve menu_items from $this->fields for this tab (may be empty for adapter-only tabs)
1472 $menu_items = isset( $this->fields[$tab_id] ) ? $this->fields[$tab_id] : [];
1473
1474 // Determine menu item for this tab
1475 $tab_menu_items = isset( $this->tabs[$tab_id]['menu_items'] ) && is_array( $this->tabs[$tab_id]['menu_items'] ) ? $this->tabs[$tab_id]['menu_items'] : [];
1476 $posted_menu_item = isset( $data[$tab_id], $data[$tab_id]['menu_item'] ) ? sanitize_key( $data[$tab_id]['menu_item'] ) : '';
1477
1478 // Resolve menu item safely for tabs with and without menu navigation.
1479 if ( $posted_menu_item !== '' ) {
1480 if ( ! empty( $tab_menu_items ) && array_key_exists( $posted_menu_item, $tab_menu_items ) )
1481 $menu_item = $posted_menu_item;
1482 elseif ( array_key_exists( $posted_menu_item, $menu_items ) )
1483 $menu_item = $posted_menu_item;
1484 else {
1485 if ( empty( $menu_items ) )
1486 continue;
1487 $menu_item = array_key_exists( 'options', $menu_items ) ? 'options' : key( $menu_items );
1488 }
1489 } else {
1490 if ( empty( $menu_items ) )
1491 continue;
1492 $menu_item = array_key_exists( 'options', $menu_items ) ? 'options' : key( $menu_items );
1493 }
1494
1495 // Resolve fields from adapter (single source for managed tabs)
1496 $items = [];
1497 if ( isset( $rl->gallery_api ) && $rl->gallery_api->is_managed_tab( $tab_id ) ) {
1498 $items = $rl->gallery_api->get_tab_fields_for_save( $tab_id, $menu_item );
1499 }
1500
1501 // Defensive fallback for images tab only (not fully adapter-owned for field definitions)
1502 if ( $tab_id === 'images' && empty( $items ) && isset( $menu_items[$menu_item] ) && is_array( $menu_items[$menu_item] ) ) {
1503 $items = $menu_items[$menu_item];
1504 }
1505
1506 if ( empty( $items ) || ! is_array( $items ) )
1507 continue;
1508
1509 // IMAGES TAB: Minimal defensive guards (sanitizer handles data structure)
1510 if ( $tab_id === 'images' ) {
1511 // Ensure folder field has valid structure for folders menu item
1512 if ( $menu_item === 'folders' && isset( $data[$tab_id][$menu_item]['folder'] ) ) {
1513 $folder = $data[$tab_id][$menu_item]['folder'];
1514 if ( ! is_array( $folder ) ) {
1515 $data[$tab_id][$menu_item]['folder'] = [ 'id' => 0, 'children' => false ];
1516 } else {
1517 if ( ! isset( $folder['id'] ) ) {
1518 $data[$tab_id][$menu_item]['folder']['id'] = 0;
1519 }
1520 if ( ! isset( $folder['children'] ) ) {
1521 $data[$tab_id][$menu_item]['folder']['children'] = false;
1522 }
1523 }
1524 }
1525 // Note: attachments['ids'] is CSV string, sanitizer handles it at line 1997
1526 }
1527
1528 // sanitize fields
1529 $safedata = $this->sanitize_fields( $items, $data, $tab_id, $menu_item );
1530
1531 // tab validation hook (adapter-managed tabs)
1532 if ( isset( $rl->gallery_api ) && $rl->gallery_api->is_managed_tab( $tab_id ) ) {
1533 if ( isset( $safedata[$tab_id][$menu_item] ) && is_array( $safedata[$tab_id][$menu_item] ) ) {
1534 $safedata[$tab_id][$menu_item] = $rl->gallery_api->validate_tab_data(
1535 $tab_id,
1536 $menu_item,
1537 $safedata[$tab_id][$menu_item],
1538 $post_id
1539 );
1540 }
1541 }
1542
1543 // add menu item
1544 $safedata[$tab_id]['menu_item'] = $menu_item;
1545
1546 // preview?
1547 if ( $preview )
1548 update_metadata( 'post', $post_id, '_rl_' . $tab_id, $safedata[$tab_id] );
1549 else
1550 update_post_meta( $post_id, '_rl_' . $tab_id, $safedata[$tab_id] );
1551 }
1552
1553 $has_featured_image_payload = isset( $post_data['rl_gallery_featured_image'] );
1554
1555 // Preserve existing featured-image metadata for partial updates (e.g. Quick Edit).
1556 if ( ! $has_featured_image_payload ) {
1557 $featured_image_type = get_post_meta( $post_id, '_rl_featured_image_type', true );
1558 $featured_image = get_post_meta( $post_id, '_rl_featured_image', true );
1559 $thumbnail_id = (int) get_post_meta( $post_id, '_thumbnail_id', true );
1560
1561 if ( ! in_array( $featured_image_type, [ 'id', 'url', 'image' ], true ) )
1562 $featured_image_type = 'image';
1563 } else {
1564 $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';
1565
1566 switch ( $featured_image_type ) {
1567 // custom url
1568 case 'url':
1569 $thumbnail_id = $this->maybe_generate_thumbnail();
1570 $frontend = function_exists( 'Responsive_Lightbox' ) ? Responsive_Lightbox()->frontend : null;
1571 $custom_url = isset( $post_data['_rl_thumbnail_url'] ) ? $post_data['_rl_thumbnail_url'] : '';
1572 if ( $frontend && method_exists( $frontend, 'sanitize_remote_image_url' ) )
1573 $featured_image = $frontend->sanitize_remote_image_url( $custom_url );
1574 else
1575 $featured_image = '';
1576
1577 if ( $featured_image === '' )
1578 $featured_image_type = 'image';
1579 break;
1580
1581 // first image
1582 case 'image':
1583 $thumbnail_id = $this->maybe_generate_thumbnail();
1584 $featured_image = '';
1585 break;
1586
1587 // attachment id
1588 case 'id':
1589 default:
1590 $featured_image = $thumbnail_id = isset( $post_data['_thumbnail_id'] ) ? (int) $post_data['_thumbnail_id'] : 0;
1591 }
1592 }
1593
1594 // preview?
1595 if ( $preview ) {
1596 update_metadata( 'post', $post_id, '_rl_featured_image_type', $featured_image_type );
1597 update_metadata( 'post', $post_id, '_rl_featured_image', $featured_image );
1598 update_metadata( 'post', $post_id, '_thumbnail_id', $thumbnail_id );
1599 } else {
1600 // update featured image
1601 update_post_meta( $post_id, '_rl_featured_image_type', $featured_image_type );
1602 update_post_meta( $post_id, '_rl_featured_image', $featured_image );
1603 update_post_meta( $post_id, '_thumbnail_id', $thumbnail_id );
1604
1605 // save number of images
1606 update_post_meta( $post_id, '_rl_images_count', $this->get_gallery_images_number( $post_id ) );
1607 }
1608
1609 // update post excerpt
1610 if ( isset( $safedata['misc']['options']['gallery_description'] ) ) {
1611 remove_action( 'save_post_rl_gallery', [ $this, 'save_post' ], 10, 3 );
1612
1613 $postdata = [
1614 'ID' => $post_id,
1615 'post_excerpt' => sanitize_textarea_field( $safedata['misc']['options']['gallery_description'] )
1616 ];
1617
1618 wp_update_post( $postdata );
1619
1620 add_action( 'save_post_rl_gallery', [ $this, 'save_post' ], 10, 3 );
1621 }
1622 }
1623
1624 /**
1625 * Display shortcode metabox.
1626 *
1627 * @param object $post
1628 * @return void
1629 */
1630 public function shortcode_metabox( $post ) {
1631 echo '
1632 <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>
1633 <code class="rl-shortcode" data-number="0">[rl_gallery id=&quot;' . (int) $post->ID . '&quot;]</code>
1634 <p>' . esc_html__( 'You can also place this gallery into your template files by using the template tag below', 'responsive-lightbox' ) . ':</p>
1635 <code class="rl-shortcode" data-number="1">if ( function_exists( \'rl_gallery\' ) ) { rl_gallery( \'' . (int) $post->ID . '\' ); }</code>';
1636 }
1637
1638 /**
1639 * Add new gallery listing columns.
1640 *
1641 * @param array $columns
1642 * @return array
1643 */
1644 public function gallery_columns( $columns ) {
1645 // find title position
1646 $offset = array_search( 'title', array_keys( $columns ) );
1647
1648 // put image column before title
1649 $columns = array_merge(
1650 array_slice( $columns, 0, $offset ),
1651 array(
1652 'image' => esc_html__( 'Gallery', 'responsive-lightbox' )
1653 ),
1654 array_slice( $columns, $offset )
1655 );
1656
1657 // put new columns after title
1658 $columns = array_merge(
1659 array_slice( $columns, 0, $offset + 2 ),
1660 array(
1661 'shortcode' => esc_html__( 'Shortcode', 'responsive-lightbox' ),
1662 'type' => esc_html__( 'Type', 'responsive-lightbox' ),
1663 'source' => esc_html__( 'Source', 'responsive-lightbox' )
1664 ),
1665 array_slice( $columns, $offset + 2 )
1666 );
1667
1668 return $columns;
1669 }
1670
1671 /**
1672 * Add new gallery listing columns content.
1673 *
1674 * @global string $pagenow
1675 *
1676 * @param string $column_name
1677 * @param int $post_id
1678 * @return void
1679 */
1680 public function gallery_columns_content( $column_name, $post_id ) {
1681 switch ( $column_name ) {
1682 case 'image':
1683 // get image data, based on gallery source type
1684 $image = $this->get_featured_image( $post_id, 'thumbnail' );
1685 $images_count = (int) get_post_meta( $post_id, '_rl_images_count', true );
1686
1687 // display count
1688 if ( ! empty( $image ) )
1689 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>';
1690 else
1691 echo '<span class="media-icon image-icon">' . wp_get_attachment_image( 0, array( 60, 60 ), true, array( 'alt' => '' ) ) . '</span>';
1692 break;
1693
1694 case 'shortcode':
1695 echo '<code>[rl_gallery id="' . (int) $post_id . '"]</code>';
1696 break;
1697
1698 case 'type':
1699 $config = get_post_meta( $post_id, '_rl_config', true );
1700
1701 if ( is_array( $config ) && ! empty( $config['menu_item'] ) && array_key_exists( $config['menu_item'], $this->tabs['config']['menu_items'] ) ) {
1702 echo esc_html( $this->tabs['config']['menu_items'][$config['menu_item']] );
1703
1704 if ( $config['menu_item'] === 'default' )
1705 echo esc_html( ' (' . $this->tabs['config']['menu_items'][Responsive_Lightbox()->options['settings']['builder_gallery']] . ')' );
1706 } else
1707 echo '-';
1708 break;
1709
1710 case 'source':
1711 $images = get_post_meta( $post_id, '_rl_images', true );
1712
1713 if ( is_array( $images ) && ! empty( $images['menu_item'] ) && array_key_exists( $images['menu_item'], $this->tabs['images']['menu_items'] ) )
1714 echo esc_html( $this->tabs['images']['menu_items'][$images['menu_item']] );
1715 else
1716 echo '-';
1717 break;
1718 }
1719 }
1720
1721 /**
1722 * Get size information for all currently-registered image sizes.
1723 *
1724 * @global array $_wp_additional_image_sizes
1725 *
1726 * @return array
1727 */
1728 public function get_image_sizes() {
1729 global $_wp_additional_image_sizes;
1730
1731 $sizes = [];
1732
1733 foreach ( get_intermediate_image_sizes() as $_size ) {
1734 if ( in_array( $_size, [ 'thumbnail', 'medium', 'medium_large', 'large' ] ) ) {
1735 $sizes[$_size]['width'] = get_option( "{$_size}_size_w" );
1736 $sizes[$_size]['height'] = get_option( "{$_size}_size_h" );
1737 $sizes[$_size]['crop'] = (bool) get_option( "{$_size}_crop" );
1738 } elseif ( isset( $_wp_additional_image_sizes[$_size] ) ) {
1739 $sizes[$_size] = [
1740 'width' => $_wp_additional_image_sizes[$_size]['width'],
1741 'height' => $_wp_additional_image_sizes[$_size]['height'],
1742 'crop' => $_wp_additional_image_sizes[$_size]['crop'],
1743 ];
1744 }
1745 }
1746
1747 return $sizes;
1748 }
1749
1750 /**
1751 * Get size information for a specific image size.
1752 *
1753 * @param string $size The image size for which to retrieve data.
1754 * @return false|array
1755 */
1756 public function get_image_size( $size ) {
1757 if ( isset( $this->sizes[$size] ) )
1758 return $this->sizes[$size];
1759 else
1760 return false;
1761 }
1762
1763 /**
1764 * Filter the admin post thumbnail HTML markup.
1765 *
1766 * @param string $content
1767 * @param int $post_id
1768 * @param int $thumbnail_id
1769 * @return string
1770 */
1771 public function admin_post_thumbnail_html( $content, $post_id, $thumbnail_id ) {
1772 if ( get_post_type( $post_id ) === 'rl_gallery' ) {
1773 $value = get_post_meta( $post_id, '_rl_featured_image', true );
1774 $frontend = function_exists( 'Responsive_Lightbox' ) ? Responsive_Lightbox()->frontend : null;
1775 if ( $frontend && method_exists( $frontend, 'sanitize_remote_image_url' ) )
1776 $value = $frontend->sanitize_remote_image_url( $value );
1777 $type = get_post_meta( $post_id, '_rl_featured_image_type', true );
1778 $type = ! empty( $type ) && in_array( $type, array( 'image', 'id', 'url' ) ) ? $type : 'image';
1779
1780 // force media library image
1781 if ( wp_doing_ajax() )
1782 $type = 'id';
1783 // post featured image is post thumbnail replacement?
1784 elseif ( $this->maybe_generate_thumbnail() === (int) $thumbnail_id ) {
1785 remove_filter( 'admin_post_thumbnail_html', array( $this, 'admin_post_thumbnail_html' ), 10 );
1786
1787 $content = _wp_post_thumbnail_html( 0, $post_id );
1788 }
1789
1790 $content = '
1791 <div class="rl-gallery-featured-image-options">
1792 <p class="howto">' . esc_html__( 'Select gallery featured image source:', 'responsive-lightbox' ) . '</p>
1793 <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 />
1794 <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 />
1795 <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>
1796 </div>
1797 <div class="rl-gallery-featured-image-select">
1798 <div class="rl-gallery-featured-image-select-id"' . ( $type === 'id' ? '' : ' style="display: none;"' ) . '>' . $content . '</div>
1799 <div class="rl-gallery-featured-image-select-url"' . ( $type === 'url' ? '' : ' style="display: none;"' ) . '>
1800 <p><input id="_rl_thumbnail_url" class="large-text" name="_rl_thumbnail_url" value="' . ( $type === 'url' ? esc_url( $value ) : '' ) . '" type="text" /></p>
1801 <p class="howto">' . esc_html__( 'Custom featured image URL', 'responsive-lightbox' ) . '</p>
1802 </div>
1803 <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>
1804 </div>
1805 ';
1806 }
1807
1808 return $content;
1809 }
1810
1811 /**
1812 * Modify the resulting HTML so that the feature image is set as a background property.
1813 *
1814 * @param string $html The HTML image tag.
1815 * @param int $post_id The post whose featured image is to be printed.
1816 * @param int $post_thumbnail_id The post thumbnail ID.
1817 * @param array|string $size The size of the featured image.
1818 * @param array $attr Additional attributes.
1819 * @return string
1820 */
1821 public function post_thumbnail_html( $html, $post_id = 0, $post_thumbnail_id = 0, $size = false, $attr = [] ) {
1822 if ( get_post_type( $post_id ) === 'rl_gallery' ) {
1823 // get featured image type
1824 $image_type = get_post_meta( $post_id, '_rl_featured_image_type', true );
1825
1826 // break if featured image type is media library
1827 if ( ! $image_type || $image_type == 'id' )
1828 return $html;
1829
1830 // get image source
1831 $image_src = $this->get_gallery_image_src( $this->get_featured_image_src( $post_id ) );
1832
1833 // no image?
1834 if ( empty( $image_src ) )
1835 return $html;
1836
1837 // add featured image as background in style tag
1838 $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;"';
1839
1840 $html = str_replace( 'src=', $style . ' src=', $html );
1841
1842 // fix the alt tag (if possible)
1843 $alt = $image_src['alt'];
1844
1845 if ( isset( $attr['alt'] ) )
1846 $alt = $attr['alt'];
1847
1848 if ( $alt ) {
1849 $html = str_replace( '/(alt=\'[^\']+\'\|alt="[^"]+")/', '', $html );
1850 $html = str_replace( 'src=', ' alt="' . esc_attr( $alt ) . '" src=', $html );
1851 }
1852 }
1853
1854 return $html;
1855 }
1856 }
1857
1858