PluginProbe ʕ •ᴥ•ʔ
Responsive Lightbox & Gallery / 2.6.0
Responsive Lightbox & Gallery v2.6.0
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
providers 1 year ago class-fast-image.php 2 years ago class-folders.php 6 months ago class-frontend.php 6 months ago class-galleries.php 6 months ago class-multilang.php 2 years ago class-remote-library-api.php 1 year ago class-remote-library.php 6 months ago class-settings.php 6 months ago class-tour.php 2 years ago class-welcome.php 2 years ago class-widgets.php 2 years ago functions.php 3 years ago
class-galleries.php
5242 lines
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Responsive Lightbox Galleries class.
8 *
9 * @class Responsive_Lightbox_Galleries
10 */
11 class Responsive_Lightbox_Galleries {
12
13 public $fields;
14 private $tabs;
15 private $sizes;
16 private $gallery_args;
17 private $menu_item;
18 private $revision_id;
19 private $allowed_select_html = [
20 'select' => [
21 'name' => true,
22 'id' => true,
23 'class' => true,
24 'required' => true,
25 'tabindex' => true,
26 'aria-describedby' => true
27 ],
28 'option' => [
29 'value' => true,
30 'class' => true,
31 'selected' => true
32 ]
33 ];
34
35
36 /**
37 * Class constructor.
38 *
39 * @param bool $read_only Whether is it read only mode
40 * @return void
41 */
42 public function __construct( $read_only = false ) {
43 // set instance
44 Responsive_Lightbox()->galleries = $this;
45
46 if ( $read_only )
47 return;
48
49 // actions
50 add_action( 'init', array( $this, 'init' ), 11 );
51 add_action( 'admin_init', array( $this, 'init_admin' ) );
52 add_action( 'current_screen', array( $this, 'clear_metaboxes' ) );
53 add_action( 'edit_form_after_title', array( $this, 'after_title_nav_menu' ) );
54 add_action( 'admin_footer', array( $this, 'modal_gallery_template' ) );
55 add_action( 'customize_controls_print_footer_scripts', array( $this, 'modal_gallery_template' ) );
56 add_action( 'media_buttons', array( $this, 'add_gallery_button' ) );
57 add_action( 'add_meta_boxes_rl_gallery', array( $this, 'add_meta_boxes' ) );
58 add_action( 'save_post_rl_gallery', array( $this, 'save_post' ), 10, 3 );
59 add_action( 'manage_rl_gallery_posts_custom_column', array( $this, 'gallery_columns_content' ), 10, 2 );
60 add_action( 'admin_action_duplicate_gallery', array( $this, 'duplicate_gallery' ) );
61 add_action( 'wp_ajax_rl-get-menu-content', array( $this, 'get_menu_content' ) );
62 add_action( 'wp_ajax_rl-get-preview-content', array( $this, 'get_gallery_preview_content' ) );
63 add_action( 'wp_ajax_rl-post-get-galleries', array( $this, 'post_get_galleries' ) );
64 add_action( 'wp_ajax_rl-post-gallery-preview', array( $this, 'post_gallery_preview' ) );
65 add_action( 'wp_ajax_rl-get-gallery-page-content', array( $this, 'get_gallery_page' ) );
66 add_action( 'wp_ajax_nopriv_rl-get-gallery-page-content', array( $this, 'get_gallery_page' ) );
67 add_action( '_wp_put_post_revision', array( $this, 'save_revision' ) );
68 add_action( 'delete_attachment', array( $this, 'delete_attachment' ) );
69 add_action( 'shutdown', array( $this, 'shutdown_preview' ) );
70 add_action( 'wp_loaded', array( $this, 'maybe_change_lightbox' ), 1 );
71
72 // filters
73 add_filter( 'manage_rl_gallery_posts_columns', array( $this, 'gallery_columns' ) );
74 add_filter( 'admin_post_thumbnail_html', array( $this, 'admin_post_thumbnail_html' ), 10, 3 );
75 add_filter( 'post_thumbnail_html', array( $this, 'post_thumbnail_html' ), 10, 5 );
76 add_filter( 'preview_post_link', array( $this, 'preview_post_link' ) );
77 add_filter( 'post_row_actions', array( $this, 'post_row_actions_duplicate' ), 10, 2 );
78
79 if ( ! empty( $_POST['rl_active_tab'] ) )
80 add_filter( 'redirect_post_location', array( $this, 'add_active_tab' ) );
81 }
82
83 /**
84 * Get class data.
85 *
86 * @param string $attr
87 * @return mixed
88 */
89 public function get_data( $attr ) {
90 return property_exists( $this, $attr ) ? $this->{$attr} : null;
91 }
92
93 /**
94 * Get default gallery single image template.
95 *
96 * @param array $args Template arguments
97 * @return string
98 */
99 public function get_media_item_template( $args = [] ) {
100 $args = array_merge(
101 array(
102 'draggable' => false,
103 'editable' => false,
104 'removable' => false,
105 'changeable' => false
106 ),
107 $args
108 );
109
110 return '
111 <li class="rl-gallery-image__MEDIA_STATUS__" data-attachment_id="__MEDIA_ID__" data-type="__MEDIA_TYPE__"' . ( $args['draggable'] ? ' style="cursor: move;"' : '' ) . '>
112 <div class="rl-gallery-inner">
113 <div class="centered">
114 __MEDIA_DATA__
115 </div>
116 </div>
117 <div class="rl-gallery-actions">' .
118 ( $args['changeable'] ? '<a href="#" class="rl-gallery-image-status dashicons dashicons-marker" title="' . esc_attr__( 'Status', 'responsive-lightbox' ) . '"></a>' : '' ) .
119 ( $args['editable'] ? '<a href="#" class="rl-gallery-image-edit dashicons dashicons-edit" title="' . esc_attr__( 'Edit image', 'responsive-lightbox' ) . '"></a>' : '' ) .
120 ( $args['removable'] ? '<a href="#" class="rl-gallery-image-remove dashicons dashicons-no" title="' . esc_attr__( 'Remove image', 'responsive-lightbox' ) . '"></a>' : '' ) . '
121 </div>
122 </li>';
123 }
124
125 /**
126 * Get default gallery embed template.
127 *
128 * @param bool $js
129 * @return string
130 */
131 public function get_media_embed_template( $js = false ) {
132 $html = '';
133
134 if ( $js )
135 $html .= '<div data-id="__EMBED_ID__" style="display: none;">';
136
137 $html .= '
138 <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][url]" data-type="url" value="__EMBED_URL__">
139 <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][width]" data-type="width" value="__EMBED_WIDTH__">
140 <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][height]" data-type="height" value="__EMBED_HEIGHT__">
141 <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][thumbnail_url]" data-type="thumbnail_url" value="__EMBED_THUMBNAIL_URL__">
142 <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][thumbnail_width]" data-type="thumbnail_width" value="__EMBED_THUMBNAIL_WIDTH__">
143 <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][thumbnail_height]" data-type="thumbnail_height" value="__EMBED_THUMBNAIL_HEIGHT__">
144 <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][title]" data-type="title" value="__EMBED_TITLE__">
145 <textarea class="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][caption]" data-type="caption">__EMBED_DESCRIPTION__</textarea>
146 <input type="hidden" name="rl_gallery[images][media][attachments][embed][__EMBED_ID__][date]" data-type="date" value="__EMBED_DATE__">';
147
148 if ( $js )
149 $html .= '</div>';
150
151 return $html;
152 }
153
154 /**
155 * Get default gallery exclude input template.
156 *
157 * @param string $tab_id
158 * @param string $menu_item
159 * @param string $field_name
160 * @param mixed $excluded_value
161 * @return string
162 */
163 public function get_media_exclude_input_template( $tab_id = '', $menu_item = '', $field_name = '', $excluded_value = '' ) {
164 $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__" />';
165
166 if ( $tab_id === '' && $menu_item === '' && $field_name === '' && $excluded_value === '' )
167 return str_replace( '__MEDIA_FIELD_VALUE__', '', $template );
168
169 return str_replace(
170 [
171 '__MEDIA_TAB_ID__',
172 '__MEDIA_MENU_ITEM__',
173 '__MEDIA_FIELD_NAME__',
174 '__MEDIA_FIELD_VALUE__'
175 ],
176 [
177 esc_attr( $tab_id ),
178 esc_attr( $menu_item ),
179 esc_attr( $field_name ),
180 empty( $excluded_value ) ? '' : esc_attr( $excluded_value )
181 ],
182 $template
183 );
184 }
185
186 /**
187 * Load needed data.
188 *
189 * @return void
190 */
191 public function init() {
192 // register shortcode
193 add_shortcode( 'rl_gallery', array( $this, 'gallery_shortcode' ) );
194
195 // get main instance
196 $rl = Responsive_Lightbox();
197
198 // set lightbox script for infinite scroll pages
199 if ( isset( $_GET['rl_gallery_no'], $_GET['rl_page'], $_GET['rl_lightbox_script'] ) )
200 $rl->set_lightbox_script( sanitize_key( $_GET['rl_lightbox_script'] ) );
201
202 $config_menu_items = apply_filters( 'rl_gallery_types', $rl->get_data( 'gallery_types' ) );
203 $config_menu_items['default'] = __( 'Global', 'responsive-lightbox' );
204
205 // set tabs
206 $this->tabs = apply_filters(
207 'rl_gallery_tabs',
208 array(
209 'images' => array(
210 'label' => __( 'Images', 'responsive-lightbox' ),
211 'description' => __( 'The settings below adjust the contents of the gallery.', 'responsive-lightbox' ),
212 'menu_items' => array(
213 'media' => __( 'Media Library', 'responsive-lightbox' ),
214 'featured' => __( 'Featured Content', 'responsive-lightbox' )
215 )
216 ),
217 'config' => array(
218 'label' => __( 'Config', 'responsive-lightbox' ),
219 'description' => __( 'The settings below adjust the configuration options for the gallery.', 'responsive-lightbox' ),
220 'menu_items' => $config_menu_items
221 ),
222 'design' => array(
223 'label' => __( 'Design', 'responsive-lightbox' ),
224 'description' => __( 'The settings below adjust the gallery design options.', 'responsive-lightbox' )
225 ),
226 'paging' => array(
227 'label' => __( 'Paging', 'responsive-lightbox' ),
228 'description' => __( 'The settings below adjust the gallery pagination options.', 'responsive-lightbox' )
229 ),
230 'lightbox' => array(
231 'label' => __( 'Lightbox', 'responsive-lightbox' ),
232 'description' => __( 'The settings below adjust the lightbox options.', 'responsive-lightbox' ),
233 ),
234 'misc' => array(
235 'label' => __( 'Misc', 'responsive-lightbox' ),
236 'description' => __( 'The settings below adjust miscellaneous options.', 'responsive-lightbox' ),
237 )
238 )
239 );
240
241 // add folders if active
242 $this->tabs['images']['menu_items']['folders'] = __( 'Media Folders', 'responsive-lightbox' );
243
244 // add remote library if active
245 $this->tabs['images']['menu_items']['remote_library'] = __( 'Remote Library', 'responsive-lightbox' );
246
247 // use sizes as keys and values
248 $this->sizes = $this->get_image_sizes();
249 $sizes = array_combine( array_keys( $this->sizes ), array_keys( $this->sizes ) );
250
251 // add default, custom and full image size
252 $sizes['full'] = __( 'Full size', 'responsive-lightbox' );
253 $sizes['global'] = __( 'Global', 'responsive-lightbox' );
254 $sizes['rl_custom_size'] = __( 'Custom size', 'responsive-lightbox' );
255
256 // positions
257 $positions = array(
258 'none' => __( 'None', 'responsive-lightbox' ),
259 'top' => __( 'Top', 'responsive-lightbox' ),
260 'bottom' => __( 'Bottom', 'responsive-lightbox' )
261 );
262
263 // merge titles
264 $merged_titles = array( 'global' => __( 'Global', 'responsive-lightbox' ) ) + $rl->settings->get_data( 'image_titles' );
265
266 // set fields
267 $this->fields = apply_filters(
268 'rl_gallery_tab_fields',
269 array(
270 'images' => array(
271 'media' => array(
272 'attachments' => array(
273 'title' => '',
274 'type' => 'media_library',
275 'default' => array(
276 'ids' => [],
277 'exclude' => [],
278 'embed' => []
279 ),
280 'preview' => array(
281 'pagination' => true,
282 'draggable' => true,
283 'editable' => true,
284 'removable' => true,
285 'changeable' => true
286 )
287 )
288 ),
289 'featured' => array(
290 'attachments' => array(
291 'title' => '',
292 'type' => 'media_preview',
293 'default' => array(
294 'exclude' => []
295 ),
296 'preview' => array(
297 'pagination' => true,
298 'draggable' => false,
299 'editable' => true,
300 'removable' => false,
301 'changeable' => false
302 )
303 ),
304 'number_of_posts' => array(
305 'title' => __( 'Number of Posts', 'responsive-lightbox' ),
306 'type' => 'number',
307 'description' => __( 'Enter the number of posts.', 'responsive-lightbox' ),
308 'default' => 10,
309 'min' => 0
310 ),
311 'orderby' => array(
312 'title' => __( 'Posts Sorting', 'responsive-lightbox' ),
313 'type' => 'select',
314 'description' => __( 'Select the posts sorting.', 'responsive-lightbox' ),
315 'default' => 'date',
316 'options' => array(
317 'id' => __( 'ID', 'responsive-lightbox' ),
318 'author' => __( 'Author', 'responsive-lightbox' ),
319 'title' => __( 'Title', 'responsive-lightbox' ),
320 'name' => __( 'Slug', 'responsive-lightbox' ),
321 'date' => __( 'Date', 'responsive-lightbox' ),
322 'modified' => __( 'Last modified date', 'responsive-lightbox' ),
323 'parent' => __( 'Parent ID', 'responsive-lightbox' ),
324 'rand' => __( 'Random', 'responsive-lightbox' )
325 )
326 ),
327 'order' => array(
328 'title' => __( 'Posts Order', 'responsive-lightbox' ),
329 'type' => 'radio',
330 'description' => __( 'Select the posts order.', 'responsive-lightbox' ),
331 'default' => 'asc',
332 'options' => array(
333 'asc' => __( 'Ascending', 'responsive-lightbox' ),
334 'desc' => __( 'Descending', 'responsive-lightbox' )
335 )
336 ),
337 'offset' => array(
338 'title' => __( 'Posts Offset', 'responsive-lightbox' ),
339 'type' => 'number',
340 'description' => __( 'Enter the posts offset.', 'responsive-lightbox' ),
341 'default' => 0,
342 'min' => 0
343 ),
344 'image_source' => array(
345 'title' => __( 'Image Source', 'responsive-lightbox' ),
346 'type' => 'radio',
347 'description' => __( 'Select the image source.', 'responsive-lightbox' ),
348 'default' => 'thumbnails',
349 'options' => array(
350 'thumbnails' => __( 'Post Thumbnails', 'responsive-lightbox' ),
351 'attached_images' => __( 'Post Attached Images', 'responsive-lightbox' )
352 )
353 ),
354 'images_per_post' => array(
355 'title' => __( 'Images per Post', 'responsive-lightbox' ),
356 'type' => 'number',
357 'description' => __( 'Enter maximum number of images for a post.', 'responsive-lightbox' ),
358 'default' => 1,
359 'min' => 1
360 ),
361 'post_type' => array(
362 'title' => __( 'Post Type', 'responsive-lightbox' ),
363 'type' => 'multiselect',
364 'description' => __( 'Select the post types to query.', 'responsive-lightbox' ),
365 'options' => [],
366 'default' => []
367 ),
368 'post_status' => array(
369 'title' => __( 'Post Status', 'responsive-lightbox' ),
370 'type' => 'multiselect',
371 'description' => __( 'Select the post status.', 'responsive-lightbox' ),
372 'options' => [],
373 'default' => []
374 ),
375 'post_format' => array(
376 'title' => __( 'Post Format', 'responsive-lightbox' ),
377 'type' => 'multiselect',
378 'description' => __( 'Select the post format.', 'responsive-lightbox' ),
379 'options' => [],
380 'default' => []
381 ),
382 'post_term' => array(
383 'title' => __( 'Post Term', 'responsive-lightbox' ),
384 'type' => 'multiselect',
385 'description' => __( 'Select the post taxonomy terms to query.', 'responsive-lightbox' ),
386 'options' => [],
387 'default' => []
388 ),
389 'post_author' => array(
390 'title' => __( 'Post Author', 'responsive-lightbox' ),
391 'type' => 'multiselect',
392 'description' => __( 'Select the post author.', 'responsive-lightbox' ),
393 'options' => [],
394 'default' => []
395 ),
396 'page_parent' => array(
397 'title' => __( 'Page Parent', 'responsive-lightbox' ),
398 'type' => 'multiselect',
399 'description' => __( 'Select the post parent.', 'responsive-lightbox' ),
400 'options' => [],
401 'default' => []
402 ),
403 'page_template' => array(
404 'title' => __( 'Page Template', 'responsive-lightbox' ),
405 'type' => 'multiselect',
406 'description' => __( 'Select the page template.', 'responsive-lightbox' ),
407 'options' => [],
408 'default' => []
409 )
410 ),
411 'folders' => array(
412 'attachments' => array(
413 'title' => '',
414 'type' => 'media_preview',
415 'default' => array(
416 'exclude' => []
417 ),
418 'preview' => array(
419 'pagination' => true,
420 'draggable' => false,
421 'editable' => true,
422 'removable' => false,
423 'changeable' => false
424 )
425 ),
426 'folder' => array(
427 'title' => __( 'Media Folder', 'responsive-lightbox' ),
428 'type' => 'taxonomy',
429 'description' => __( 'Select media folder.', 'responsive-lightbox' ),
430 'default' => array(
431 'id' => 0,
432 'children' => false
433 ),
434 'include_children' => true,
435 'taxonomy' => $rl->options['folders']['media_taxonomy']
436 )
437 ),
438 'remote_library' => array(
439 'attachments' => array(
440 'title' => '',
441 'type' => 'media_preview',
442 'default' => array(
443 'exclude' => []
444 ),
445 'preview' => array(
446 'pagination' => true,
447 'draggable' => false,
448 'editable' => false,
449 'removable' => false,
450 'changeable' => false
451 )
452 ),
453 'media_search' => array(
454 'title' => __( 'Search string', 'responsive-lightbox' ),
455 'type' => 'text',
456 'description' => __( 'Enter the search phrase.', 'responsive-lightbox' ),
457 'default' => ''
458 ),
459 'media_provider' => array(
460 'title' => __( 'Media Providers', 'responsive-lightbox' ),
461 'type' => 'select',
462 'description' => __( 'Select which remote library should be used.', 'responsive-lightbox' ),
463 'default' => 'all',
464 'options' => array(
465 'all' => __( 'All Media Providers', 'responsive-lightbox' )
466 )
467 ),
468 'response_data' => array(
469 'title' => '',
470 'type' => 'hidden',
471 'description' => '',
472 'default' => '',
473 'callback' => array( $rl->remote_library, 'remote_library_response_data' )
474 )
475 )
476 ),
477 'config' => [],
478 'design' => array(
479 'options' => array(
480 'design_show_title' => array(
481 'title' => __( 'Thumbnail title', 'responsive-lightbox' ),
482 'type' => 'select',
483 'description' => __( 'Select title for the gallery thumbnails.', 'responsive-lightbox' ),
484 'default' => 'global',
485 'options' => $merged_titles
486 ),
487 'design_show_caption' => array(
488 'title' => __( 'Thumbnail caption', 'responsive-lightbox' ),
489 'type' => 'select',
490 'description' => __( 'Select caption for the gallery thumbnails.', 'responsive-lightbox' ),
491 'default' => 'global',
492 'options' => $merged_titles
493 ),
494 'show_icon' => array(
495 'title' => __( 'Thumbnail icon', 'responsive-lightbox' ),
496 'type' => 'radio',
497 'description' => __( 'Select icon for the gallery thumbnails.', 'responsive-lightbox' ),
498 'default' => '0',
499 'options' => array(
500 '0' => __( 'none', 'responsive-lightbox' ),
501 '1' => '',
502 '2' => '',
503 '3' => '',
504 '4' => '',
505 '5' => '',
506 '6' => '',
507 '7' => '',
508 '8' => '',
509 '9' => '',
510 '10' => ''
511 )
512 ),
513 'hover_effect' => array(
514 'title' => __( 'Hover effect', 'responsive-lightbox' ),
515 'type' => 'select',
516 'description' => __( 'Select thumbnail effect on hover.', 'responsive-lightbox' ),
517 'default' => '0',
518 'options' => array(
519 '0' => __( 'none', 'responsive-lightbox' ),
520 '1' => sprintf( __( 'Effect %s', 'responsive-lightbox' ), 1 ),
521 '2' => sprintf( __( 'Effect %s', 'responsive-lightbox' ), 2 ),
522 '3' => sprintf( __( 'Effect %s', 'responsive-lightbox' ), 3 ),
523 '4' => sprintf( __( 'Effect %s', 'responsive-lightbox' ), 4 ),
524 '5' => sprintf( __( 'Effect %s', 'responsive-lightbox' ), 5 ),
525 '6' => sprintf( __( 'Effect %s', 'responsive-lightbox' ), 6 ),
526 '7' => sprintf( __( 'Effect %s', 'responsive-lightbox' ), 7 ),
527 '8' => sprintf( __( 'Effect %s', 'responsive-lightbox' ), 8 ),
528 '9' => sprintf( __( 'Effect %s', 'responsive-lightbox' ), 9 )
529 )
530 ),
531 'caption_font_size' => array(
532 'title' => __( 'Caption Font Size', 'responsive-lightbox' ),
533 'type' => 'number',
534 'default' => 13,
535 'step' => 1,
536 'min' => 10,
537 'max' => 20,
538 'append' => 'px'
539 ),
540 'caption_padding' => array(
541 'title' => __( 'Caption Padding', 'responsive-lightbox' ),
542 'type' => 'number',
543 'default' => 20,
544 'step' => 1,
545 'min' => 5,
546 'max' => 30,
547 'append' => 'px'
548 ),
549 'title_color' => array(
550 'title' => __( 'Title Color', 'responsive-lightbox' ),
551 'type' => 'color_picker',
552 'default' => '#ffffff'
553 ),
554 'caption_color' => array(
555 'title' => __( 'Caption Color', 'responsive-lightbox' ),
556 'type' => 'color_picker',
557 'default' => '#cccccc'
558 ),
559 'background_color' => array(
560 'title' => __( 'Background Color', 'responsive-lightbox' ),
561 'type' => 'color_picker',
562 'default' => '#000000'
563 ),
564 'background_opacity' => array(
565 'title' => __( 'Background Opacity', 'responsive-lightbox' ),
566 'type' => 'number',
567 'default' => 80,
568 'step' => 1,
569 'min' => 0,
570 'max' => 100,
571 'append' => '%'
572 ),
573 'border_color' => array(
574 'title' => __( 'Border Color', 'responsive-lightbox' ),
575 'type' => 'color_picker',
576 'default' => '#000000'
577 ),
578 'border_width' => array(
579 'title' => __( 'Border Width', 'responsive-lightbox' ),
580 'type' => 'number',
581 'default' => 0,
582 'step' => 1,
583 'min' => 0,
584 'max' => 100,
585 'append' => 'px'
586 )
587 )
588 ),
589 'paging' => array(
590 'options' => array(
591 'pagination' => array(
592 'title' => __( 'Use pagination', 'responsive-lightbox' ),
593 'type' => 'boolean',
594 'label' => __( 'Enable pagination.', 'responsive-lightbox' ),
595 'default' => false
596 ),
597 'pagination_type' => array(
598 'title' => __( 'Pagination type', 'responsive-lightbox' ),
599 'type' => 'select',
600 'description' => __( 'Select pagination type.', 'responsive-lightbox' ),
601 'default' => 'paged',
602 'options' => array(
603 'paged' => __( 'standard', 'responsive-lightbox' ),
604 'ajax' => __( 'AJAX', 'responsive-lightbox' ),
605 'infinite' => __( 'infinite scroll', 'responsive-lightbox' )
606 )
607 ),
608 'pagination_position' => array(
609 'title' => __( 'Pagination position', 'responsive-lightbox' ),
610 'type' => 'select',
611 'description' => __( 'Select pagination position.', 'responsive-lightbox' ),
612 'default' => 'bottom',
613 'options' => array(
614 'bottom' => __( 'bottom', 'responsive-lightbox' ),
615 'top' => __( 'top', 'responsive-lightbox' ),
616 'both' => __( 'top & bottom', 'responsive-lightbox' )
617 )
618 ),
619 'images_per_page' => array(
620 'title' => __( 'Images per page', 'responsive-lightbox' ),
621 'type' => 'number',
622 'description' => __( 'Number of images per page.', 'responsive-lightbox' ),
623 'default' => get_option( 'posts_per_page', 20 ),
624 'step' => 1,
625 'min' => 0
626 ),
627 'load_more' => array(
628 'title' => __( 'Load More', 'responsive-lightbox' ),
629 'type' => 'radio',
630 'description' => __( 'Select the load more trigger (infinite scroll only).', 'responsive-lightbox' ),
631 'default' => 'automatically',
632 'options' => array(
633 'automatically' => __( 'Automatically', 'responsive-lightbox' ),
634 'manually' => __( 'On click', 'responsive-lightbox' )
635 )
636 )
637 )
638 ),
639 'lightbox' => array(
640 'options' => array(
641 'lightbox_enable' => array(
642 'title' => __( 'Enable Lightbox', 'responsive-lightbox' ),
643 'type' => 'boolean',
644 'label' => __( 'Enable lightbox effect for the gallery.', 'responsive-lightbox' ),
645 'default' => true
646 ),
647 'lightbox_image_size' => array(
648 'title' => __( 'Image Size', 'responsive-lightbox' ),
649 'type' => 'select',
650 'description' => __( 'Select image size for gallery lightbox.', 'responsive-lightbox' ),
651 'default' => 'global',
652 'options' => $sizes
653 ),
654 'lightbox_custom_size' => array(
655 'title' => __( 'Custom size', 'responsive-lightbox' ),
656 'type' => 'multiple',
657 'description' => __( 'Choose the custom image size for gallery lightbox (used if Custom Image size is selected).', 'responsive-lightbox' ),
658 'fields' => array(
659 'lightbox_custom_size_width' => array(
660 'type' => 'number',
661 'append' => __( 'width in px', 'responsive-lightbox' ),
662 'default' => (int) get_option( 'large_size_w' )
663 ),
664 'lightbox_custom_size_height' => array(
665 'type' => 'number',
666 'append' => __( 'height in px', 'responsive-lightbox' ),
667 'default' => (int) get_option( 'large_size_h' )
668 )
669 )
670 ),
671 'lightbox_image_title' => array(
672 'title' => __( 'Image Title', 'responsive-lightbox' ),
673 'type' => 'select',
674 'description' => __( 'Select image title for gallery lightbox.', 'responsive-lightbox' ),
675 'default' => 'global',
676 'options' => $merged_titles
677 ),
678 'lightbox_image_caption' => array(
679 'title' => __( 'Image Caption', 'responsive-lightbox' ),
680 'type' => 'select',
681 'description' => __( 'Select image caption for gallery lightbox (used if supported by selected lightbox effect).', 'responsive-lightbox' ),
682 'default' => 'global',
683 'options' => $merged_titles
684 )
685 )
686 ),
687 'misc' => array(
688 'options' => array(
689 'gallery_title_position' => array(
690 'title' => __( 'Title Position', 'responsive-lightbox' ),
691 'type' => 'select',
692 'description' => __( 'Select where to display the title.', 'responsive-lightbox' ),
693 'default' => 'none',
694 'options' => $positions
695 ),
696 'gallery_description_position' => array(
697 'title' => __( 'Description Position', 'responsive-lightbox' ),
698 'type' => 'select',
699 'description' => __( 'Select where to display the description.', 'responsive-lightbox' ),
700 'default' => 'none',
701 'options' => $positions
702 ),
703 'gallery_description' => array(
704 'title' => __( 'Gallery Description', 'responsive-lightbox' ),
705 'type' => 'textarea',
706 'description' => __( 'Enter the gallery description (optional).', 'responsive-lightbox' ),
707 'default' => '',
708 'class' => 'large-text'
709 ),
710 'gallery_custom_class' => array(
711 'title' => __( 'Custom Classes', 'responsive-lightbox' ),
712 'type' => 'class',
713 'description' => __( 'Add custom, space saparated CSS classes (optional).', 'responsive-lightbox' ),
714 'default' => '',
715 'class' => 'large-text'
716 )
717 )
718 )
719 )
720 );
721
722 // is remote library active?
723 if ( $rl->options['remote_library']['active'] ) {
724 // get providers
725 $providers = $rl->remote_library->get_providers();
726 $active_providers = $rl->remote_library->get_active_providers();
727
728 // update active providers
729 foreach ( $active_providers as $provider ) {
730 $this->fields['images']['remote_library']['media_provider']['options'][$provider] = $providers[$provider]['name'];
731 }
732 }
733 }
734
735 /**
736 * Duplicate gallery action in admin.
737 *
738 * @return void
739 */
740 public function duplicate_gallery() {
741 if ( ! ( isset( $_GET['post'] ) || isset( $_POST['post'] ) ) || ! isset( $_REQUEST['action'] ) || ! isset( $_REQUEST['rl_gallery_nonce'] ) || ( isset( $_REQUEST['rl_gallery_nonce'] ) && ! wp_verify_nonce( $_REQUEST['rl_gallery_nonce'], 'responsive-lightbox-duplicate-gallery' ) ) )
742 wp_die( esc_html__( 'No gallery to duplicate has been supplied!', 'responsive-lightbox' ) );
743
744 // get the original post
745 $post_id = isset( $_GET['post'] ) ? (int) $_GET['post'] : ( isset( $_POST['post'] ) ? (int) $_POST['post'] : 0 );
746
747 if ( empty( $post_id ) )
748 wp_die( esc_html__( 'No gallery to duplicate has been supplied!', 'responsive-lightbox' ) );
749
750 if ( ! current_user_can( 'edit_post', $post_id ) )
751 wp_die( esc_html__( 'You do not have permission to copy this gallery.', 'responsive-lightbox' ) );
752
753 $post = get_post( $post_id );
754
755 // copy the post and insert it
756 if ( isset( $post ) && $post !== null ) {
757 $this->create_gallery_duplicate( $post );
758
759 // redirect to the post list screen
760 wp_redirect( admin_url( 'edit.php?post_type=' . $post->post_type ) );
761 exit;
762 } else
763 wp_die( esc_html__( 'Copy creation failed, could not find original gallery:', 'responsive-lightbox' ) . ' ' . (int) $post_id );
764 }
765
766 /**
767 * Add duplicate link to gallery listing.
768 *
769 * @global string $pagenow
770 *
771 * @param array $actions Link actions
772 * @param object $post Post object
773 * @return array
774 */
775 public function post_row_actions_duplicate( $actions, $post ) {
776 global $pagenow;
777
778 if ( $post->post_type !== 'rl_gallery' )
779 return $actions;
780
781 if ( ! current_user_can( 'edit_post', $post->ID ) )
782 return $actions;
783
784 // duplicate link
785 $actions['duplicate_gallery'] = '<a class="duplicate-gallery" title="' . esc_attr__( 'Duplicate this item', 'responsive-lightbox' ) . '" href="' . esc_url( wp_nonce_url( admin_url( $pagenow . '?post=' . $post->ID . '&action=duplicate_gallery' ), 'responsive-lightbox-duplicate-gallery', 'rl_gallery_nonce' ) ) . '">' . esc_html__( 'Duplicate', 'responsive-lightbox' ) . '</a>';
786
787 return $actions;
788 }
789
790 /**
791 * Create a gallery duplicate.
792 *
793 * @param $post object Post object
794 * @return void|int
795 */
796 public function create_gallery_duplicate( $post ) {
797 // skip revisions
798 if ( $post->post_type === 'revision' )
799 return;
800
801 $new_post = apply_filters(
802 'rl_duplicate_gallery_args',
803 [
804 'menu_order' => $post->menu_order,
805 'comment_status' => $post->comment_status,
806 'ping_status' => $post->ping_status,
807 'post_author' => $post->post_author,
808 'post_content' => $post->post_content,
809 'post_excerpt' => $post->post_excerpt,
810 'post_mime_type' => $post->post_mime_type,
811 'post_parent' => $post->post_parent,
812 'post_password' => $post->post_password,
813 'post_status' => $post->post_status,
814 'post_title' => $post->post_title,
815 'post_type' => $post->post_type,
816 'post_date' => current_time( 'mysql' ),
817 'post_date_gmt' => get_gmt_from_date( current_time( 'mysql' ) )
818 ],
819 $post
820 );
821
822 $new_post_id = wp_insert_post( $new_post );
823
824 // if the copy is published or scheduled, we have to set a proper slug
825 if ( $new_post['post_status'] === 'publish' || $new_post['post_status'] === 'future' ) {
826 $post_name = wp_unique_post_slug( $post->post_name, $new_post_id, $new_post['post_status'], $post->post_type, $new_post['post_parent'] );
827
828 $new_post = [];
829 $new_post['ID'] = $new_post_id;
830 $new_post['post_name'] = $post_name;
831
832 // update the post into the database
833 wp_update_post( $new_post );
834 }
835
836 // create metadata for the duplicated gallery
837 $this->create_gallery_duplicate_metadata( $new_post_id, $post );
838
839 // copy taxonomies
840 $this->duplicate_gallery_taxonomies( $new_post_id, $post );
841
842 // action hook for developers
843 do_action( 'rl_after_duplicate_gallery', $new_post_id, $post );
844
845 return $new_post_id;
846 }
847
848 /**
849 * Create a gallery duplicate metadata.
850 *
851 * @param int $new_post_id Post ID
852 * @param object $post Post object
853 * @return void
854 */
855 public function create_gallery_duplicate_metadata( $new_post_id, $post ) {
856 if ( empty( $post ) || $post == null )
857 return;
858
859 // meta keys to be copied
860 $meta_keys = apply_filters( 'rl_duplicate_gallery_meta_keys', get_post_custom_keys( $post->ID ) );
861
862 if ( empty( $meta_keys ) )
863 return;
864
865 foreach ( $meta_keys as $meta_key ) {
866 // meta values to be copied
867 $meta_values = apply_filters( 'rl_duplicate_gallery_meta_values', get_post_custom_values( $meta_key, $post->ID ) );
868
869 foreach ( $meta_values as $meta_value ) {
870 $meta_value = maybe_unserialize( $meta_value );
871
872 // add metadata to duplicated post
873 add_post_meta( $new_post_id, $meta_key, $meta_value );
874 }
875 }
876 }
877
878 /**
879 * Copy the taxonomies of a gallery to another gallery.
880 *
881 * @global object $wpdb
882 *
883 * @param int $new_post_id Post ID
884 * @param object $post Post object
885 * @return void
886 */
887 function duplicate_gallery_taxonomies( $new_post_id, $post ) {
888 global $wpdb;
889
890 if ( isset( $wpdb->terms ) ) {
891 // clear default category
892 wp_set_object_terms( $new_post_id, null, 'category' );
893
894 // get gallery taxonomies
895 $gallery_taxonomies = get_object_taxonomies( $post->post_type );
896
897 if ( ! empty( $gallery_taxonomies ) ) {
898 foreach ( $gallery_taxonomies as $taxonomy ) {
899 $terms = [];
900
901 // get taxonomy terms
902 $post_terms = wp_get_object_terms( $post->ID, $taxonomy, array( 'orderby' => 'term_order' ) );
903
904 if ( ! empty( $post_terms ) ) {
905 foreach ( $post_terms as $term ) {
906 $terms[] = $term->slug;
907 }
908 }
909
910 // copy taxonomy terms
911 wp_set_object_terms( $new_post_id, $terms, $taxonomy );
912 }
913 }
914 }
915 }
916
917 /**
918 * Add a gallery shortcode.
919 *
920 * @param array $args Shortcode arguments
921 * @return string
922 */
923 public function gallery_shortcode( $args ) {
924 // enable only for frontend previews
925 if ( ! is_admin() && is_preview() )
926 add_filter( 'get_post_metadata', array( $this, 'filter_preview_metadata' ), 10, 4 );
927
928 // prepare defaults
929 $defaults = [ 'id' => 0 ];
930
931 // merge defaults with arguments
932 $args = array_merge( $defaults, $args );
933
934 // parse id
935 $args['id'] = (int) $args['id'];
936
937 // is it gallery?
938 if ( get_post_type( $args['id'] ) !== 'rl_gallery' )
939 return '';
940
941 // private gallery?
942 if ( get_post_status( $args['id'] ) === 'private' && ! current_user_can( 'read_private_posts' ) )
943 return '';
944
945 $images_args = [ 'exclude' => true ];
946
947 if ( isset( $args['preview'] ) )
948 $images_args['preview'] = (bool) $args['preview'];
949 elseif( isset( $_GET['rl_gallery_revision_id'], $_GET['preview'] ) && $_GET['preview'] === 'true' )
950 $images_args['preview'] = true;
951 else
952 $images_args['preview'] = false;
953
954 // get images
955 $images = $this->get_gallery_images( $args['id'], $images_args );
956
957 if ( ! $images )
958 return '';
959
960 $attachments = [];
961
962 // build config
963 foreach ( $images as $image ) {
964 if ( ! empty( $image['id'] ) )
965 $attachments[] = $image['id'];
966 }
967
968 // get config data
969 $config = get_post_meta( $args['id'], '_rl_config', true );
970
971 // prepare gallery shortcode parameters
972 $fields = [];
973
974 // get main instance
975 $rl = Responsive_Lightbox();
976
977 // valid menu item?
978 if ( ! empty( $config['menu_item'] ) ) {
979 // assign data from db
980 $data = $config[$config['menu_item']];
981
982 foreach ( $rl->frontend->get_default_gallery_fields() as $field_name => $field_args ) {
983 // replace default values
984 if ( array_key_exists( $field_name, $data ) )
985 $fields[$field_name] = $data[$field_name];
986 }
987
988 // is it default gallery type?
989 if ( $config['menu_item'] === 'default' ) {
990 // set new gallery type
991 $gallery_type = $rl->options['settings']['builder_gallery'];
992
993 // assign gallery settings
994 if ( array_key_exists( $gallery_type . '_gallery', $rl->settings->settings ) )
995 $gallery_fields = $rl->settings->settings[$gallery_type . '_gallery']['fields'];
996
997 // assign gallery defaults
998 if ( array_key_exists( $gallery_type . '_gallery', $rl->options ) )
999 $gallery_defaults = $rl->options[$gallery_type . '_gallery'];
1000 } else {
1001 $gallery_type = $config['menu_item'];
1002
1003 // assign gallery settings
1004 if ( array_key_exists( $config['menu_item'] . '_gallery', $rl->settings->settings ) )
1005 $gallery_fields = $rl->settings->settings[$config['menu_item'] . '_gallery']['fields'];
1006
1007 // assign gallery defaults
1008 if ( array_key_exists( $config['menu_item'] . '_gallery', $rl->defaults ) )
1009 $gallery_defaults = $rl->defaults[$config['menu_item'] . '_gallery'];
1010 }
1011
1012 if ( isset( $gallery_fields, $gallery_defaults ) ) {
1013 // run through all fields
1014 foreach ( $gallery_fields as $field_name => $field_args ) {
1015 if ( $field_args['type'] === 'multiple' ) {
1016 foreach ( $field_args['fields'] as $subfield_name => $subfield_args ) {
1017 // field exists in db?
1018 if ( array_key_exists( $subfield_name, $data ) )
1019 $fields[$subfield_name] = $data[$subfield_name];
1020 else
1021 $fields[$subfield_name] = $gallery_defaults[$subfield_name];
1022 }
1023 } else {
1024 // field exists in db?
1025 if ( array_key_exists( $field_name, $data ) )
1026 $fields[$field_name] = $data[$field_name];
1027 else
1028 $fields[$field_name] = $gallery_defaults[$field_name];
1029 }
1030 }
1031 }
1032 // add gallery type
1033 $fields['type'] = $gallery_type;
1034 }
1035
1036 $shortcode = '';
1037
1038 foreach ( $fields as $arg => $value ) {
1039 if ( is_array( $value ) )
1040 $shortcode .= ' ' . esc_attr( $arg ) . '="' . esc_attr( (string) implode( ',', $value ) ) . '"';
1041 else
1042 $shortcode .= ' ' . esc_attr( $arg ) . '="' . esc_attr( (string) $value ) . '"';
1043 }
1044
1045 // get design data
1046 $design = get_post_meta( $args['id'], '_rl_design', true );
1047
1048 if ( ! empty( $design['menu_item'] ) ) {
1049 $design_data = $design[$design['menu_item']];
1050
1051 // remove show_title to avoid shortcode attribute duplication
1052 if ( isset( $design_data['show_title'] ) ) {
1053 if ( ! isset( $design_data['design_show_title'] ) )
1054 $design_data['design_show_title'] = $design_data['show_title'];
1055
1056 unset( $design_data['show_title'] );
1057 }
1058
1059 // remove show_caption to avoid shortcode attribute duplication
1060 if ( isset( $design_data['show_caption'] ) ) {
1061 if ( ! isset( $design_data['design_show_caption'] ) )
1062 $design_data['design_show_caption'] = $design_data['show_caption'];
1063
1064 unset( $design_data['show_caption'] );
1065 }
1066
1067 foreach ( $design_data as $arg => $value ) {
1068 $shortcode .= ' ' . esc_attr( $arg ) . '="' . esc_attr( (string) $value ) . '"';
1069 }
1070 }
1071
1072 // get lightbox data
1073 $lightbox = get_post_meta( $args['id'], '_rl_lightbox', true );
1074
1075 if ( ! empty( $lightbox['menu_item'] ) ) {
1076 foreach ( $lightbox[$lightbox['menu_item']] as $arg => $value ) {
1077 $shortcode .= ' ' . esc_attr( $arg ) . '="' . esc_attr( (string) $value ) . '"';
1078 }
1079 }
1080
1081 $forced_gallery_no = 0;
1082
1083 // check forced gallery number
1084 if ( isset( $args['gallery_no'] ) ) {
1085 $args['gallery_no'] = (int) $args['gallery_no'];
1086
1087 if ( $args['gallery_no'] > 0 )
1088 $forced_gallery_no = $args['gallery_no'];
1089 }
1090
1091 // get content
1092 $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 . ']' );
1093
1094 // make sure every filter is available in frontend ajax
1095 if ( wp_doing_ajax() )
1096 $content = $rl->frontend->add_lightbox( $content );
1097
1098 return $content;
1099 }
1100
1101 /**
1102 * Add a gallery button.
1103 *
1104 * @param string $editor_id Editor ID
1105 * @return void
1106 */
1107 public function add_gallery_button( $editor_id ) {
1108 if ( get_post_type() === 'rl_gallery' )
1109 return;
1110
1111 $this->enqueue_gallery_scripts_styles();
1112
1113 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>';
1114 }
1115
1116 /**
1117 * Enqueue scripts and styles needed for gallery modal.
1118 *
1119 * @global string $pagenow
1120 *
1121 * @return void
1122 */
1123 public function enqueue_gallery_scripts_styles() {
1124 global $pagenow;
1125
1126 // count how many times function was executed
1127 static $run = 0;
1128
1129 // allow this only once
1130 if ( $run > 0 )
1131 return;
1132
1133 $run++;
1134
1135 // get main instance
1136 $rl = Responsive_Lightbox();
1137
1138 wp_enqueue_script( 'responsive-lightbox-admin-gallery', RESPONSIVE_LIGHTBOX_URL . '/js/admin-gallery.js', array( 'jquery', 'underscore' ), $rl->defaults['version'], false );
1139
1140 // prepare script data
1141 $script_data = [
1142 'nonce' => wp_create_nonce( 'rl-gallery-post' ),
1143 'post_id' => get_the_ID(),
1144 'page' => esc_url( $pagenow )
1145 ];
1146
1147 wp_add_inline_script( 'responsive-lightbox-admin-gallery', 'var rlArgsGallery = ' . wp_json_encode( $script_data ) . ";\n", 'before' );
1148
1149 wp_enqueue_style( 'responsive-lightbox-admin-gallery', RESPONSIVE_LIGHTBOX_URL . '/css/admin-gallery.css', [], $rl->defaults['version'] );
1150 }
1151
1152 /**
1153 * Modal gallery HTML template.
1154 *
1155 * @global string $wp_version
1156 * @global string $pagenow
1157 *
1158 * @return void
1159 */
1160 public function modal_gallery_template() {
1161 global $wp_version;
1162 global $pagenow;
1163
1164 // display only for post edit pages
1165 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' ) ) ) )
1166 return;
1167
1168 // get main instance
1169 $rl = Responsive_Lightbox();
1170
1171 $categories = '';
1172
1173 // builder categories?
1174 if ( $rl->options['builder']['categories'] ) {
1175 $terms = get_terms(
1176 array(
1177 'taxonomy' => 'rl_category',
1178 'orderby' => 'name',
1179 'order' => 'ASC',
1180 'hide_empty' => false,
1181 'fields' => 'id=>name'
1182 )
1183 );
1184
1185 // get categories dropdown
1186 $categories = wp_dropdown_categories(
1187 array(
1188 'orderby' => 'name',
1189 'order' => 'asc',
1190 'show_option_none' => empty( $terms ) ? __( 'All categories', 'responsive-lightbox' ) : '',
1191 'show_option_all' => __( 'All categories', 'responsive-lightbox' ),
1192 'show_count' => false,
1193 'hide_empty' => false,
1194 'option_none_value' => 0,
1195 'hierarchical' => true,
1196 'selected' => 0,
1197 'taxonomy' => 'rl_category',
1198 'hide_if_empty' => false,
1199 'echo' => false,
1200 'id' => 'rl-media-attachment-categories',
1201 'class' => 'attachment-filters',
1202 'name' => ''
1203 )
1204 );
1205 }
1206
1207 echo '
1208 <div id="rl-modal-gallery" style="display: none;">
1209 <div class="media-modal wp-core-ui">
1210 <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>
1211 <div class="media-modal-content">
1212 <div class="media-frame mode-select wp-core-ui hide-menu hide-router">
1213 <div class="media-frame-title">
1214 <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>
1215 </div>
1216 <div class="media-frame-content" data-columns="0">
1217 <div class="attachments-browser">
1218 <div class="uploader-inline rl-no-galleries" style="display: none;">
1219 <div class="uploader-inline-content has-upload-message">
1220 <h2 class="upload-message">' . esc_html__( 'No items found.', 'responsive-lightbox' ) . '</h2>
1221 <div class="upload-ui">
1222 <h2 class="upload-instructions">' . esc_html__( 'No galleries? Create them first or try another search phrase.', 'responsive-lightbox' ) . '</h2>
1223 </div>
1224 </div>
1225 </div>
1226 <div class="media-toolbar">' . ( $rl->options['builder']['categories'] ? '
1227 <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>' : '' ) . '
1228 <div class="media-toolbar-primary search-form">
1229 <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">
1230 </div>
1231 </div>
1232 <ul class="attachments rl-galleries-list ui-sortable ui-sortable-disabled">
1233 </ul>
1234 <div class="media-sidebar visible">
1235 <h2>' . esc_html__( 'Select A Gallery', 'responsive-lightbox' ) . '</h2>
1236 <p>' . esc_html__( 'To select a gallery simply click on one of the boxes to the left.', 'responsive-lightbox' ) . '</p>
1237 <p>' . esc_html__( 'To insert your gallery into the editor, click on the "Insert Gallery" button below.', 'responsive-lightbox' ) . '</p>
1238 </div>
1239 </div>
1240 </div>
1241 <div class="media-frame-toolbar">
1242 <div class="media-toolbar">
1243 <div class="media-toolbar-secondary">
1244 <div class="media-selection empty">
1245 <div class="selection-info">
1246 <span class="rl-gallery-count count">' . esc_html( sprintf( _n( '%s image', '%s images', 0, 'responsive-lightbox' ), 0 ) ) . '</span>
1247 <a href="" class="button-link rl-edit-gallery-link">' . esc_html__( 'Edit gallery', 'responsive-lightbox' ) . '</a>
1248 </div>
1249 <div class="selection-view">
1250 <span class="rl-gallery-images-spinner spinner" style="display: none;"></span>
1251 <ul class="attachments rl-attachments-list">
1252 </ul>
1253 </div>
1254 </div>
1255 </div>
1256 <div class="media-toolbar-primary search-form">
1257 <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>
1258 <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>
1259 <button type="button" class="button media-button button-secondary button-large rl-media-button-cancel-gallery">' . esc_html__( 'Cancel', 'responsive-lightbox') . '</button>
1260 </div>
1261 </div>
1262 </div>
1263 </div>
1264 </div>
1265 </div>
1266 <div class="media-modal-backdrop"></div>
1267 </div>';
1268 }
1269
1270 /**
1271 * Render gallery field.
1272 *
1273 * @param string $field Field name
1274 * @param string $tab_id Field tab
1275 * @param string $menu_item Field parent
1276 * @param array $args Field arguments
1277 * @param int $gallery_id Gallery ID
1278 * @param bool $subfield Is this a subfield
1279 * @return string
1280 */
1281 public function render_field( $field, $tab_id, $menu_item, $args, $gallery_id, $subfield = false ) {
1282 if ( $subfield ) {
1283 $template = '%s%s';
1284 $html = '';
1285 $subhtml = '';
1286 } else {
1287 $template = $args['type'] === 'section' ? '<th colspan="2"><h3>%s</h3></th>' : '<th><label for="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field ) . '">%s</label></th><td>%s</td>';
1288 $html = '<tr class="rl-gallery-field-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field ) . ' rl-gallery-field-' . esc_attr( $args['type'] ) . '" data-field_type="' . esc_attr( $args['type'] ) . '" data-field_name="' . esc_attr( $field ) . '">';
1289 $subhtml = '';
1290 }
1291
1292 switch ( $args['type'] ) {
1293 case 'range':
1294 $html .= sprintf(
1295 $template,
1296 ! empty( $args['title'] ) ? esc_html( $args['title'] ) : '',
1297 '<input id="rl_' . esc_attr( $tab_id . '_' . $menu_item . '_' . $field ) . '" type="range" value="' . (int) $args['value'] . '" name="rl_gallery[' . esc_attr( $tab_id ) . '][' . esc_attr( $menu_item ) . '][' . esc_attr( $field ) . ']" min="' . ( ! empty( $args['min'] ) ? (int) $args['min'] : 0 ) . '"' . ( ! empty( $args['max'] ) ? ' max="' . (int) $args['max'] . '"' : '' ) . ' step="' . ( ! empty( $args['step'] ) ? (int) $args['step'] : 1 ) . '" oninput="this.form.rl_' . esc_attr( $tab_id ) . '_' . esc_attr( $menu_item ) . '_' . esc_attr( $field ) . '_range.value=this.value" /><output class="rl-gallery-field-output" name="rl_' . esc_attr( $tab_id ) . '_' . esc_attr( $menu_item ) . '_' . esc_attr( $field ) . '_range">' . (int) $args['value'] . '</output>' . ( ! empty( $args['append'] ) ? ' <span>' . esc_html( $args['append'] ) . '</span>' : '' ) . ( ! empty ( $args['description'] ) ? '<p class="description">' . wp_kses_post( $args['description'] ) . '</p>' : '' )
1298 );
1299 break;
1300
1301 case 'radio':
1302 $subhtml = '';
1303
1304 foreach ( $args['options'] as $key => $label ) {
1305 $subhtml .= '<label class="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field ) . '" for="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field . '-' . $key ) . '"><input id="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field . '-' . $key ) . '" type="radio" name="rl_gallery[' . esc_attr( $tab_id ) . '][' . esc_attr( $menu_item ) . '][' . esc_attr( $field ) . ']" value="' . esc_attr( $key ) . '" ' . checked( $key, $args['value'], false ) . ' />' . esc_html( $label ) . '</label> ';
1306 }
1307
1308 $html .= sprintf(
1309 $template,
1310 ! empty( $args['title'] ) ? esc_html( $args['title'] ) : '',
1311 $subhtml . ( ! empty ( $args['description'] ) ? '<p class="description">' . wp_kses_post( $args['description'] ) . '</p>' : '' )
1312 );
1313 break;
1314
1315 case 'number':
1316 $html .= sprintf(
1317 $template,
1318 ! empty( $args['title'] ) ? esc_html( $args['title'] ) : '',
1319 '<input id="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field ) . '" class="small-text" type="number" value="' . esc_attr( $args['value'] ) . '" name="rl_gallery[' . esc_attr( $tab_id ) . '][' . esc_attr( $menu_item ) . '][' . esc_attr( $field ) . ']" min="' . ( ! empty( $args['min'] ) ? (int) $args['min'] : 0 ) . '"' . ( ! empty( $args['max'] ) ? ' max="' . (int) $args['max'] . '"' : '' ) . ' step="' . ( ! empty( $args['step'] ) ? (int) $args['step'] : 1 ) . '" />' . ( ! empty( $args['append'] ) ? ' <span>' . esc_html( $args['append'] ) . '</span>' : '' ) . ( ! empty ( $args['description'] ) ? '<p class="description">' . wp_kses_post( $args['description'] ) . '</p>' : '' )
1320 );
1321 break;
1322
1323 case 'text':
1324 $html .= sprintf(
1325 $template,
1326 ! empty( $args['title'] ) ? esc_html( $args['title'] ) : '',
1327 '<input id="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field ) . '"' . ( ! empty( $args['class'] ) ? ' class="' . esc_attr( $args['class'] ) . '"' : '' ) . ' type="text" value="' . esc_attr( $args['value'] ) . '" name="rl_gallery[' . esc_attr( $tab_id ) . '][' . esc_attr( $menu_item ) . '][' . esc_attr( $field ) . ']" />' . ( ! empty ( $args['description'] ) ? '<p class="description">' . wp_kses_post( $args['description'] ) . '</p>' : '' )
1328 );
1329 break;
1330
1331 case 'class':
1332 case 'textarea':
1333 $html .= sprintf(
1334 $template,
1335 ! empty( $args['title'] ) ? esc_html( $args['title'] ) : '',
1336 '<textarea id="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field ) . '"' . ( ! empty( $args['class'] ) ? ' class="' . esc_attr( $args['class'] ) . '"' : '' ) . ' name="rl_gallery[' . esc_attr( $tab_id ) . '][' . esc_attr( $menu_item ) . '][' . esc_attr( $field ) . ']">' . esc_textarea( $args['value'] ) . '</textarea>' . ( ! empty ( $args['description'] ) ? '<p class="description">' . wp_kses_post( $args['description'] ) . '</p>' : '' )
1337 );
1338 break;
1339
1340 case 'select':
1341 $subhtml = '<select id="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field ) . '" name="rl_gallery[' . esc_attr( $tab_id ) . '][' . esc_attr( $menu_item ) . '][' . esc_attr( $field ) . ']">';
1342
1343 foreach ( $args['options'] as $key => $label ) {
1344 $subhtml .= '
1345 <option value="' . esc_attr( $key ) . '" ' . selected( $args['value'], $key, false ) . '>' . esc_html( $label ) . '</option>';
1346 }
1347
1348 $html .= sprintf(
1349 $template,
1350 ! empty( $args['title'] ) ? esc_html( $args['title'] ) : '',
1351 $subhtml . '</select>' . ( ! empty ( $args['description'] ) ? '<p class="description">' . wp_kses_post( $args['description'] ) . '</p>' : '' )
1352 );
1353 break;
1354
1355 case 'taxonomy':
1356 if ( taxonomy_exists( $args['taxonomy'] ) ) {
1357 $subhtml = wp_dropdown_categories(
1358 array(
1359 'orderby' => 'name',
1360 'order' => 'asc',
1361 'show_option_none' => __( 'Root Folder', 'responsive-lightbox' ),
1362 'show_option_all' => false,
1363 'show_count' => false,
1364 'hide_empty' => false,
1365 'option_none_value' => 0,
1366 'hierarchical' => true,
1367 'selected' => $args['value']['id'],
1368 'taxonomy' => $args['taxonomy'],
1369 'hide_if_empty' => false,
1370 'echo' => false,
1371 'id' => 'rl-' . $tab_id . '-' . $menu_item . '-' . $field,
1372 'name' => 'rl_gallery[' . $tab_id . '][' . $menu_item . '][' . $field . '][id]'
1373 )
1374 );
1375 } else
1376 $subhtml = '<select id="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field ) . '" name="rl_gallery[' . esc_attr( $tab_id ) . '][' . esc_attr( $menu_item ) . '][' . esc_attr( $field ) . '][]" ><option value="0">' . esc_html__( 'Root Folder', 'responsive-lightbox' ) . '</option></select> ';
1377
1378 if ( isset( $args['include_children'] ) && $args['include_children'] ) {
1379 $subhtml .= '<label class="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field ) . '-include-children" for="rl-' . esc_attr( $tab_id ) . '-' . esc_attr( $menu_item ) . '-' . esc_attr( $field ) . '-include-children"><input id="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field ) . '-include-children" type="checkbox" name="rl_gallery[' . esc_attr( $tab_id ) . '][' . esc_attr( $menu_item ) . '][' . esc_attr( $field ) . '][children]" value="true" ' . checked( $args['value']['children'], true, false ) . ' />' . esc_html__( 'Include children.', 'responsive-lightbox' ) . '</label>';
1380 }
1381
1382 $html .= sprintf(
1383 $template,
1384 ! empty( $args['title'] ) ? esc_html( $args['title'] ) : '',
1385 $subhtml . ( ! empty ( $args['description'] ) ? '<p class="description">' . wp_kses_post( $args['description'] ) . '</p>' : '' )
1386 );
1387 break;
1388
1389 case 'multiselect':
1390 $subhtml = '<select multiple="multiple" class="select2" id="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field ) . '" data-empty="' . (int) empty( $args['value'] ) . '" data-type="' . esc_attr( $field ) . '" name="rl_gallery[' . esc_attr( $tab_id ) . '][' . esc_attr( $menu_item ) . '][' . esc_attr( $field ) . '][]">';
1391
1392 if ( $field === 'post_term' ) {
1393 foreach ( $args['options'] as $taxanomy => $data ) {
1394 $subhtml .= '<optgroup label="' . esc_attr( $data['label'] ) . '">';
1395
1396 foreach ( $data['terms'] as $term_id => $name ) {
1397 $subhtml .= '<option value="' . esc_attr( $term_id ) . '" ' . selected( in_array( $term_id, $args['value'], false ), true, false ) . '>' . esc_html( $name ) . '</option>';
1398 }
1399
1400 $subhtml .= '</optgroup>';
1401 }
1402 } else {
1403 foreach ( $args['options'] as $key => $label ) {
1404 $subhtml .= '
1405 <option value="' . esc_attr( $key ) . '" ' . selected( in_array( $key, $args['value'], false ), true, false ) . '>' . esc_html( $label ) . '</option>';
1406 }
1407 }
1408
1409 $html .= sprintf(
1410 $template,
1411 ! empty( $args['title'] ) ? esc_html( $args['title'] ) : '',
1412 $subhtml . '</select>' . ( ! empty ( $args['description'] ) ? '<p class="description">' . wp_kses_post( $args['description'] ) . '</p>' : '' )
1413 );
1414 break;
1415
1416 case 'boolean':
1417 $html .= sprintf(
1418 $template,
1419 ! empty( $args['title'] ) ? esc_html( $args['title'] ) : '',
1420 '<label class="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field ) . '" for="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field ) . '"><input id="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field ) . '" type="checkbox" name="rl_gallery[' . esc_attr( $tab_id ) . '][' . esc_attr( $menu_item ) . '][' . esc_attr( $field ) . ']" value="true" ' . checked( $args['value'], true, false ) . ' />' . esc_html( $args['label'] ) . '</label>' . ( ! empty ( $args['description'] ) ? '<p class="description">' . wp_kses_post( $args['description'] ) . '</p>' : '' )
1421 );
1422 break;
1423
1424 case 'checkbox':
1425 $subhtml = '';
1426
1427 foreach ( $args['options'] as $key => $label ) {
1428 $subhtml .= '<label class="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field . '-' . $key ) . '" for="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field . '-' . $key ) . '"><input id="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field . '-' . $key ) . '" type="checkbox" name="rl_gallery[' . esc_attr( $tab_id ) . '][' . esc_attr( $menu_item ) . '][' . esc_attr( $field ) . '][' . esc_attr( $key ) . ']" value="true" ' . checked( in_array( $key, $args['value'], true ), true, false ) . ' />' . esc_html( $label ) . '</label><br />';
1429 }
1430
1431 $html .= sprintf(
1432 $template,
1433 ! empty( $args['title'] ) ? esc_html( $args['title'] ) : '',
1434 $subhtml . ( ! empty ( $args['description'] ) ? '<p class="description">' . wp_kses_post( $args['description'] ) . '</p>' : '' )
1435 );
1436 break;
1437
1438 case 'multiple':
1439 $subhtml = '';
1440
1441 foreach ( $args['fields'] as $sub_field => $sub_args ) {
1442 $subhtml .= $this->render_field( $sub_field, $tab_id, $menu_item, $sub_args, $gallery_id, true ) . '<br />';
1443 }
1444
1445 $html .= sprintf(
1446 $template,
1447 ! empty( $args['title'] ) ? esc_html( $args['title'] ) : '',
1448 $subhtml . ( ! empty ( $args['description'] ) ? '<p class="description">' . wp_kses_post( $args['description'] ) . '</p>' : '' )
1449 );
1450 break;
1451
1452 case 'color_picker':
1453 $html .= sprintf(
1454 $template,
1455 ! empty( $args['title'] ) ? esc_html( $args['title'] ) : '',
1456 '<input id="rl-' . esc_attr( $tab_id . '-' . $menu_item . '-' . $field ) . '" class="color-picker" type="text" value="' . esc_attr( $args['value'] ) . '" name="rl_gallery[' . esc_attr( $tab_id ) . '][' . esc_attr( $menu_item ) . '][' . esc_attr( $field ) . ']" data-default-color="' . esc_attr( $args['default'] ) . '" />' . ( ! empty ( $args['description'] ) ? '<p class="description">' . wp_kses_post( $args['description'] ) . '</p>' : '' )
1457 );
1458 break;
1459
1460 case 'media_library':
1461 $data = get_post_meta( $gallery_id, '_rl_images', true );
1462
1463 // get images
1464 if ( ( ! empty( $data['menu_item'] ) && $data['menu_item'] === 'media' ) || ! ( wp_doing_ajax() && isset( $_POST['action'] ) && $_POST['action'] === 'rl-get-menu-content' ) )
1465 $images = $this->get_gallery_images( $gallery_id );
1466 else
1467 $images = [];
1468
1469 // get media item template
1470 $media_item_template = $this->get_media_item_template( $args['preview'] );
1471
1472 // media buttons
1473 $buttons_desc = '';
1474
1475 // video support?
1476 if ( rl_current_lightbox_supports( 'video' ) ) {
1477 $buttons = [ '<a href="#" class="rl-gallery-select button button-secondary">' . __( 'Select images & videos', 'responsive-lightbox' ) . '</a>' ];
1478
1479 } else {
1480 $buttons[] = '<a href="#" class="rl-gallery-select button button-secondary">' . __( 'Select images', 'responsive-lightbox' ) . '</a>';
1481 $buttons[] = '<a href="#" class="rl-gallery-select button button-disabled" disabled="true">' . __( 'Select images & videos', 'responsive-lightbox' ) . '</a>';
1482 $buttons_desc_args = [ '<a href="http://www.dfactory.co/products/fancybox-pro/" target="_blank">Fancybox Pro</a>', '<a href="http://www.dfactory.co/products/lightgallery-lightbox/" target="_blank">Lightgallery Lightbox</a>', '<a href="http://www.dfactory.co/products/lightcase-lightbox/" target="_blank">Lightcase Lightbox</a>' ];
1483 $buttons_desc = '<p class="description">' . wp_sprintf( __( 'HTML5 Videos and Embed Videos available only in %l.', 'responsive-lightbox' ), $buttons_desc_args ) . '</p>';
1484 }
1485
1486 $html .= '
1487 <td colspan="2" class="rl-colspan">
1488 <input type="hidden" class="rl-gallery-ids" name="rl_gallery[' . esc_attr( $tab_id ) . '][' . esc_attr( $menu_item ) . '][' . esc_attr( $field ) . '][ids]" value="' . esc_attr( ! empty( $args['value']['ids'] ) ? implode( ',', $args['value']['ids'] ) : '' ) . '">';
1489
1490 // embed video support?
1491 if ( rl_current_lightbox_supports( [ 'youtube', 'vimeo' ], 'OR' ) )
1492 $buttons[] = '<a href="#" class="rl-gallery-select-videos button button-secondary">' . esc_html__( 'Embed videos', 'responsive-lightbox' ) . '</a>';
1493 else
1494 $buttons[] = '<a href="#" class="rl-gallery-select-videos button button-disabled" disabled="true">' . esc_html__( 'Embed videos', 'responsive-lightbox' ) . '</a>';
1495
1496 // add buttons
1497 $html .= '
1498 <div class="rl-gallery-buttons">'
1499 . implode( '', $buttons )
1500 . $buttons_desc .
1501 '</div>';
1502
1503 $html .= '
1504 <div class="rl-gallery-content">
1505 <ul class="rl-gallery-images rl-gallery-images-media">';
1506
1507 if ( ! empty( $images ) ) {
1508 foreach ( $images as $image ) {
1509 if ( $image['id'] === 0 )
1510 $excluded_item = $image['url'];
1511 else
1512 $excluded_item = $image['id'];
1513
1514 // get image content html
1515 $html .= $this->get_gallery_preview_image_content( $image, $tab_id, $menu_item, $field, $media_item_template, $args['value']['exclude'], $excluded_item );
1516 }
1517 }
1518
1519 $html .= '
1520 </ul>
1521 </div>
1522 </td>';
1523 break;
1524
1525 case 'media_preview':
1526 $this->menu_item = $menu_item;
1527
1528 // get images
1529 $images = $this->get_gallery_images( $gallery_id );
1530
1531 // get media item template
1532 $media_item_template = $this->get_media_item_template( $args['preview'] );
1533
1534 $html .= '
1535 <td colspan="2" class="rl-colspan">
1536 <div class="rl-gallery-preview-inside">
1537 <a href="#" class="rl-gallery-update-preview button button-secondary">' . esc_html__( 'Update preview', 'responsive-lightbox' ) . '</a><span class="spinner" style="display: none;"></span>
1538 <p class="description">' . esc_html__( 'Use this button after any change of the options below to see updated gallery preview.', 'responsive-lightbox' ) . '</p>
1539 </div>
1540 <div class="rl-gallery-content">
1541 <ul class="rl-gallery-images rl-gallery-images-' . esc_attr( $menu_item ) . '">';
1542
1543 if ( ! empty( $images ) ) {
1544 foreach ( $images as $image ) {
1545 if ( empty( $image['id'] ) ) {
1546 $excluded_item = $image['url'];
1547 $image['id'] = 0;
1548 } else
1549 $excluded_item = $image['id'];
1550
1551 // get image content html
1552 $html .= $this->get_gallery_preview_image_content( $image, $tab_id, $menu_item, $field, $media_item_template, $args['value']['exclude'], $excluded_item );
1553 }
1554 }
1555
1556 $html .= '
1557 </ul>
1558 </div>';
1559
1560 if ( ! empty( $args['preview'] ) && isset( $args['preview']['pagination'] )&& $args['preview']['pagination'] )
1561 $html .= $this->get_preview_pagination();
1562
1563 $html .= '
1564 </td>';
1565 break;
1566
1567 case 'hidden':
1568 // prepare args
1569 $args['tab_id'] = $tab_id;
1570 $args['menu_item'] = $menu_item;
1571 $args['field'] = $field;
1572
1573 $html .= sprintf(
1574 $template,
1575 '',
1576 call_user_func( $args['callback'], $args )
1577 );
1578 break;
1579
1580 default:
1581 $html .= sprintf(
1582 $template,
1583 ! empty( $args['title'] ) ? esc_html( $args['title'] ) : '',
1584 apply_filters( 'rl_render_gallery_field_' . $args['type'], $subhtml, $field, $tab_id, $menu_item, $args, $subfield ) . ( ! empty ( $args['description'] ) ? '<p class="description">' . wp_kses_post( $args['description'] ) . '</p>' : '' )
1585 );
1586 }
1587
1588 if ( ! $subfield )
1589 $html .= '</tr>';
1590
1591 return apply_filters( 'rl_render_gallery_field', $html, $field, $tab_id, $menu_item, $args, $subfield, $gallery_id );
1592 }
1593
1594 /**
1595 * Get preview pagination.
1596 *
1597 * @param int $current_page
1598 * @return string
1599 */
1600 public function get_preview_pagination( $current_page = 1 ) {
1601 $page_links = [];
1602 $total_pages = $current_page + 1;
1603 $current = $current_page;
1604 $disable_first = $disable_last = $disable_prev = $disable_next = false;
1605 $current_url = 'preview_page';
1606
1607 if ( $current == 1 ) {
1608 $disable_first = true;
1609 $disable_prev = true;
1610 } elseif ( $current == 2 )
1611 $disable_first = true;
1612
1613 if ( $current == $total_pages ) {
1614 $disable_last = true;
1615 $disable_next = true;
1616 }
1617
1618 if ( $current == $total_pages - 1 )
1619 $disable_last = true;
1620
1621 if ( $disable_first )
1622 $page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&laquo;</span>';
1623 else {
1624 $page_links[] = sprintf(
1625 '<a class="first-page button" href="%s"><span class="screen-reader-text">%s</span><span aria-hidden="true">%s</span></a>',
1626 $current_url,
1627 esc_html__( 'First page', 'responsive-lightbox' ),
1628 '&laquo;'
1629 );
1630 }
1631
1632 if ( $disable_prev )
1633 $page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&lsaquo;</span>';
1634 else {
1635 $page_links[] = sprintf(
1636 '<a class="prev-page button" href="%s"><span class="screen-reader-text">%s</span><span aria-hidden="true">%s</span></a>',
1637 $current_url . '/' . max( 1, $current - 1 ),
1638 esc_html__( 'Previous page', 'responsive-lightbox' ),
1639 '&lsaquo;'
1640 );
1641 }
1642
1643 $html_current_page = sprintf(
1644 '%s<input disabled="disabled" class="current-page" id="current-page-selector" type="text" name="paged" value="%s" size="%d" aria-describedby="table-paging" /><span class="tablenav-paging-text">',
1645 '<label for="current-page-selector" class="screen-reader-text">' . esc_html__( 'Current Page', 'responsive-lightbox' ) . '</label>',
1646 $current,
1647 strlen( $total_pages )
1648 );
1649
1650 $html_total_pages = sprintf( '<span class="total-pages">%s</span>', number_format_i18n( $total_pages ) );
1651 $page_links[] = '<span class="paging-input">' . sprintf( _x( '%1$s', 'paging' ), $html_current_page, $html_total_pages ) . '</span></span>';
1652
1653 if ( $disable_next )
1654 $page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&rsaquo;</span>';
1655 else {
1656 $page_links[] = sprintf(
1657 '<a class="next-page button" href="%s"><span class="screen-reader-text">%s</span><span aria-hidden="true">%s</span></a>',
1658 $current_url . '/' . min( $total_pages, $current + 1 ),
1659 esc_html__( 'Next page', 'responsive-lightbox' ),
1660 '&rsaquo;'
1661 );
1662 }
1663
1664 if ( $disable_last )
1665 $page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&raquo;</span>';
1666 else {
1667 $page_links[] = sprintf(
1668 '<a class="last-page button" href="%s"><span class="screen-reader-text">%s</span><span aria-hidden="true">%s</span></a>',
1669 $current_url . '/' . $total_pages,
1670 esc_html__( 'Last page', 'responsive-lightbox' ),
1671 '&raquo;'
1672 );
1673 }
1674
1675 if ( $total_pages )
1676 $page_class = $total_pages < 2 ? 'one-page' : '';
1677 else
1678 $page_class = 'no-pages';
1679
1680 return '<div class="rl-gallery-preview-pagination tablenav"><div class="tablenav-pages ' . esc_attr( $page_class ) . '"><span class="pagination-links">' . join( "\n", $page_links ) . '</span></div>';
1681 }
1682
1683 /**
1684 * Sanitize field based on type. Internal use only.
1685 *
1686 * @global string $wp_version
1687 *
1688 * @param string $field Field name
1689 * @param mixed $value Field value
1690 * @param array $args Field arguments
1691 * @return mixed
1692 */
1693 public function sanitize_field( $field, $value, $args ) {
1694 switch ( $args['type'] ) {
1695 case 'radio':
1696 case 'select':
1697 $value = array_key_exists( $value, $args['options'] ) ? $value : $args['default'];
1698 break;
1699
1700 case 'taxonomy':
1701 if ( is_array( $value ) ) {
1702 if ( isset( $value['id'] ) )
1703 $value['id'] = (int) $value['id'];
1704 else
1705 $value['id'] = 0;
1706
1707 $value['children'] = isset( $value['children'] );
1708 } else
1709 $value = $args['default'];
1710
1711 // get term
1712 $term = get_term( $value['id'], $args['taxonomy'] );
1713
1714 // valid term?
1715 if ( is_a( $term, 'WP_Term' ) )
1716 $value['id'] = $term->term_id;
1717 else
1718 $value['id'] = 0;
1719 break;
1720
1721 case 'multiselect':
1722 if ( is_array( $value ) ) {
1723 // is it post term field?
1724 if ( $field === 'post_term' ) {
1725 $terms = [];
1726
1727 foreach ( $args['options'] as $data ) {
1728 $terms += $data['terms'];
1729 }
1730
1731 $args['options'] = $terms;
1732 }
1733
1734 $values = [];
1735
1736 foreach ( $value as $subvalue ) {
1737 if ( array_key_exists( $subvalue, $args['options'] ) )
1738 $values[] = $subvalue;
1739 }
1740
1741 $value = $values;
1742 } else
1743 $value = $args['default'];
1744 break;
1745
1746 case 'checkbox':
1747 if ( is_array( $value ) && ! empty( $value ) ) {
1748 $sort = [];
1749
1750 foreach ( $value as $sort_key => $bool ) {
1751 if ( array_key_exists( $sort_key, $args['options'] ) )
1752 $sort[] = $sort_key;
1753 }
1754
1755 $value = $sort;
1756 } else
1757 $value = [];
1758 break;
1759
1760 case 'boolean':
1761 $value = $value === 'true';
1762 break;
1763
1764 case 'range':
1765 case 'number':
1766 $value = (int) $value;
1767
1768 // is value lower than?
1769 if ( isset( $args['min'] ) && $value < $args['min'] )
1770 $value = $args['min'];
1771
1772 // is value greater than?
1773 if ( isset( $args['max'] ) && $value > $args['max'] )
1774 $value = $args['max'];
1775 break;
1776
1777 case 'class':
1778 $value = trim( $value );
1779
1780 // more than 1 class?
1781 if ( strpos( $value, ' ' ) !== false ) {
1782 // get unique valid HTML classes
1783 $value = array_unique( array_filter( array_map( 'sanitize_html_class', explode( ' ', $value ) ) ) );
1784
1785 if ( ! empty( $value ) )
1786 $value = implode( ' ', $value );
1787 else
1788 $value = '';
1789 // single class
1790 } else
1791 $value = sanitize_html_class( $value );
1792 break;
1793
1794 case 'text':
1795 $value = trim( sanitize_text_field( $value ) );
1796 break;
1797
1798 case 'textarea':
1799 global $wp_version;
1800
1801 // WP 4.7+
1802 if ( version_compare( $wp_version, '4.7', '>=' ) )
1803 $value = trim( sanitize_textarea_field( $value ) );
1804 // _sanitize_text_fields
1805 else {
1806 $value = wp_check_invalid_utf8( $value );
1807
1808 if ( strpos( $value, '<' ) !== false ) {
1809 $value = wp_pre_kses_less_than( $value );
1810
1811 // this will strip extra whitespace for us
1812 $value = wp_strip_all_tags( $value, false );
1813
1814 // use html entities in a special case to make sure no later newline stripping stage could lead to a functional tag
1815 $value = str_replace( "<\n", "&lt;\n", $value );
1816 }
1817
1818 $value = trim( $value );
1819 $found = false;
1820
1821 while ( preg_match('/%[a-f0-9]{2}/i', $value, $match ) ) {
1822 $value = str_replace( $match[0], '', $value );
1823 $found = true;
1824 }
1825
1826 // strip out the whitespace that may now exist after removing the octets
1827 if ( $found )
1828 $value = trim( preg_replace( '/ +/', ' ', $value ) );
1829 }
1830 break;
1831
1832 case 'color_picker':
1833 if ( preg_match( '/^#[a-f0-9]{6}$/i', $value ) !== 1 )
1834 $value = $args['default'];
1835 break;
1836
1837 case 'media_library':
1838 if ( is_array( $value ) ) {
1839 $data = $args['default'];
1840
1841 if ( rl_current_lightbox_supports( [ 'youtube', 'vimeo' ], 'OR' ) ) {
1842 $reindexed_embed = [];
1843
1844 // check embed items
1845 if ( array_key_exists( 'embed', $value ) && is_array( $value['embed'] ) && ! empty( $value['embed'] ) ) {
1846 $copy = $value['embed'];
1847
1848 $index = 0;
1849
1850 foreach ( $value['embed'] as $embed_id => $embed_data ) {
1851 // check url
1852 if ( ! array_key_exists( 'url', $embed_data ) ) {
1853 unset( $copy[$embed_id] );
1854
1855 continue;
1856 } else
1857 $copy[$embed_id]['url'] = esc_url_raw( $embed_data['url'] );
1858
1859 // check width
1860 if ( ! array_key_exists( 'width', $embed_data ) )
1861 $copy[$embed_id]['width'] = 0;
1862 else
1863 $copy[$embed_id]['width'] = (int) $embed_data['width'];
1864
1865 // check height
1866 if ( ! array_key_exists( 'height', $embed_data ) )
1867 $copy[$embed_id]['height'] = 0;
1868 else
1869 $copy[$embed_id]['height'] = (int) $embed_data['height'];
1870
1871 // check thumbnail url
1872 if ( empty( $embed_data['thumbnail_url'] ) )
1873 $copy[$embed_id]['thumbnail_url'] = '';
1874 else
1875 $copy[$embed_id]['thumbnail_url'] = esc_url_raw( $embed_data['thumbnail_url'] );
1876
1877 // check thumbnail width
1878 if ( ! array_key_exists( 'thumbnail_width', $embed_data ) )
1879 $copy[$embed_id]['thumbnail_width'] = 0;
1880 else
1881 $copy[$embed_id]['thumbnail_width'] = (int) $embed_data['thumbnail_width'];
1882
1883 // check thumbnail height
1884 if ( ! array_key_exists( 'thumbnail_height', $embed_data ) )
1885 $copy[$embed_id]['thumbnail_height'] = 0;
1886 else
1887 $copy[$embed_id]['thumbnail_height'] = (int) $embed_data['thumbnail_height'];
1888
1889 // check title
1890 if ( empty( $embed_data['title'] ) )
1891 $copy[$embed_id]['title'] = '';
1892 else
1893 $copy[$embed_id]['title'] = trim( sanitize_text_field( $embed_data['title'] ) );
1894
1895 // check caption
1896 if ( empty( $embed_data['caption'] ) )
1897 $copy[$embed_id]['caption'] = '';
1898 else
1899 $copy[$embed_id]['caption'] = trim( sanitize_textarea_field( $embed_data['caption'] ) );
1900
1901 // check date
1902 if ( empty( $embed_data['date'] ) )
1903 $copy[$embed_id]['date'] = '';
1904 else
1905 $copy[$embed_id]['date'] = date( 'Y-m-d H:i:s', strtotime( $embed_data['date'] ) );
1906
1907 // new embed id
1908 $new_id = 'e' . $index;
1909
1910 // add embed data
1911 $data['embed'][$new_id] = $copy[$embed_id];
1912 $data['embed'][$new_id]['id'] = $new_id;
1913
1914 // add special id
1915 $reindexed_embed[$embed_id] = 'em' . $index++;
1916 }
1917
1918 // last replacement is 'em' to avoid replacing same embed ids
1919 $reindexed_embed['em'] = 'e';
1920
1921 // prepare embed additional data
1922 $atts_args = [
1923 'embed_keys' => array_keys( $data['embed'] ),
1924 'providers' => [ 'youtube', 'vimeo' ]
1925 ];
1926 } else
1927 $atts_args = [];
1928 } else
1929 $atts_args = [];
1930
1931
1932 // check ids
1933 if ( array_key_exists( 'ids', $value ) ) {
1934 // prepare ids
1935 $ids = (string) trim( $value['ids'] );
1936
1937 if ( $ids !== '' ) {
1938 // reindex embed
1939 if ( ! empty( $reindexed_embed ) )
1940 $ids = str_replace( array_keys( $reindexed_embed ), array_values( $reindexed_embed ), $ids );
1941
1942 // get unique and non empty attachment ids only
1943 $data['ids'] = $this->check_attachments( array_unique( array_filter( explode( ',', $ids ) ) ), $atts_args );
1944 } else
1945 $data['ids'] = [];
1946 }
1947
1948 // check excluded items
1949 if ( array_key_exists( 'exclude', $value ) && is_array( $value['exclude'] ) && ! empty( $value['exclude'] ) ) {
1950 // reindex embed
1951 if ( ! empty( $reindexed_embed ) )
1952 $value['exclude'] = explode( ',', str_replace( array_keys( $reindexed_embed ), array_values( $reindexed_embed ), implode( ',', array_filter( $value['exclude'] ) ) ) );
1953
1954 // get unique and non empty attachment ids only
1955 $data['exclude'] = $this->check_attachments( array_unique( array_filter( $value['exclude'] ) ), $atts_args );
1956 }
1957
1958 $value = $data;
1959 } else
1960 $value = $args['default'];
1961 break;
1962
1963 case 'media_preview':
1964 if ( is_array( $value ) ) {
1965 $data = $args['default'];
1966
1967 // check excluded items
1968 if ( array_key_exists( 'exclude', $value ) && is_array( $value['exclude'] ) && ! empty( $value['exclude'] ) ) {
1969 $ids = $strings = [];
1970
1971 foreach ( $value['exclude'] as $exclude_item ) {
1972 $item = trim( $exclude_item );
1973
1974 if ( is_numeric( $item ) )
1975 $ids[] = (int) $item;
1976 elseif ( $item !== '' )
1977 $strings[] = $item;
1978 }
1979
1980 if ( ! empty( $ids ) ) {
1981 // get unique and non empty attachment ids only
1982 $ids = $this->check_attachments( array_unique( array_filter( $ids ) ) );
1983 }
1984
1985 $data['exclude'] = $ids + $strings;
1986 }
1987
1988 $value = $data;
1989 } else
1990 $value = $args['default'];
1991 }
1992
1993 return apply_filters( 'rl_sanitize_gallery_field', $value, $args );
1994 }
1995
1996 /**
1997 * Sanitize set of fields.
1998 *
1999 * @param array $items Fields
2000 * @param array $data POST data
2001 * @param string $tab_id Gallery tab
2002 * @param string $menu_item Gallery menu item
2003 * @return array
2004 */
2005 public function sanitize_fields( $items, $data, $tab_id, $menu_item ) {
2006 $safedata = [];
2007
2008 foreach ( $items as $field => $item ) {
2009 // skip this field
2010 if ( isset( $item['save'] ) && ! $item['save'] )
2011 continue;
2012
2013 // available field?
2014 if ( isset( $data[$tab_id], $data[$tab_id][$menu_item], $data[$tab_id][$menu_item][$field] ) )
2015 $safedata[$tab_id][$menu_item][$field] = $this->sanitize_field( $field, $data[$tab_id][$menu_item][$field], $item );
2016 // boolean field?
2017 elseif ( $item['type'] === 'boolean' )
2018 $safedata[$tab_id][$menu_item][$field] = false;
2019 // multiple fields?
2020 elseif ( $item['type'] === 'multiple' ) {
2021 foreach ( $item['fields'] as $subfield => $subitem ) {
2022 // available subfield?
2023 if ( isset( $data[$tab_id], $data[$tab_id][$menu_item], $data[$tab_id][$menu_item][$subfield] ) )
2024 $safedata[$tab_id][$menu_item][$subfield] = $this->sanitize_field( $subfield, $data[$tab_id][$menu_item][$subfield], $subitem );
2025 // boolean subfield?
2026 elseif ( $subitem['type'] === 'boolean' )
2027 $safedata[$tab_id][$menu_item][$subfield] = false;
2028 // any other case
2029 else
2030 $safedata[$tab_id][$menu_item][$subfield] = $subitem['default'];
2031 }
2032 // any other case
2033 } else
2034 $safedata[$tab_id][$menu_item][$field] = $item['default'];
2035 }
2036
2037 return $safedata;
2038 }
2039
2040 /**
2041 * Add menu tabs after the post title.
2042 *
2043 * @global array $wp_meta_boxes
2044 *
2045 * @param object $post Post object
2046 * @return void
2047 */
2048 public function after_title_nav_menu( $post ) {
2049 if ( $post->post_type !== 'rl_gallery' )
2050 return;
2051
2052 global $wp_meta_boxes;
2053
2054 // check active tab
2055 $active_tab = isset( $_GET['rl_active_tab'] ) ? sanitize_key( $_GET['rl_active_tab'] ) : '';
2056 $active_tab = ! empty( $active_tab ) && array_key_exists( $active_tab, $this->tabs ) ? $active_tab : 'images';
2057
2058 echo '
2059 <h2 class="nav-tab-wrapper">';
2060
2061 foreach ( $this->tabs as $key => $data ) {
2062 echo '
2063 <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>';
2064 }
2065
2066 echo '
2067 </h2>';
2068
2069 do_meta_boxes( $post->post_type, 'responsive_lightbox_metaboxes', $post );
2070
2071 unset( $wp_meta_boxes[$post->post_type]['responsive_lightbox_metaboxes'] );
2072 }
2073
2074 /**
2075 * Add class to hide metabox.
2076 *
2077 * @param array $classes
2078 * @return array
2079 */
2080 public function hide_metabox( $classes ) {
2081 $classes[] = 'rl-metabox-content';
2082 $classes[] = 'rl-hide-metabox';
2083
2084 return $classes;
2085 }
2086
2087 /**
2088 * Add class to display the metabox.
2089 *
2090 * @param array $classes
2091 * @return array
2092 */
2093 function display_metabox( $classes ) {
2094 $classes[] = 'rl-metabox-content';
2095 $classes[] = 'rl-display-metabox';
2096
2097 return $classes;
2098 }
2099
2100 /**
2101 * Add active tab to post redirect destination URL.
2102 *
2103 * @param string $location Destination URL
2104 * @return string
2105 */
2106 function add_active_tab( $location ) {
2107 // check active tab
2108 $active_tab = isset( $_POST['rl_active_tab'] ) ? sanitize_key( $_POST['rl_active_tab'] ) : '';
2109
2110 return add_query_arg( 'rl_active_tab', ! empty( $active_tab ) && array_key_exists( $active_tab, $this->tabs ) ? $active_tab : 'images', $location );
2111 }
2112
2113 /**
2114 * Add metaboxes.
2115 *
2116 * @return void
2117 */
2118 public function add_meta_boxes() {
2119 // check active tab
2120 $active_tab = isset( $_GET['rl_active_tab'] ) ? sanitize_key( $_GET['rl_active_tab'] ) : '';
2121 $active_tab = ! empty( $active_tab ) && array_key_exists( $active_tab, $this->tabs ) ? $active_tab : 'images';
2122
2123 // normal metaboxes
2124 foreach ( $this->tabs as $key => $args ) {
2125 if ( $key === 'images' )
2126 $new_args = $args + array( 'tab_id' => $key, 'active_tab' => $active_tab );
2127 else
2128 $new_args = $args + array( 'tab_id' => $key );
2129
2130 // handle metabox class
2131 if ( $active_tab === $key )
2132 add_filter( 'postbox_classes_rl_gallery_responsive-gallery-' . $key, array( $this, 'display_metabox' ) );
2133 else
2134 add_filter( 'postbox_classes_rl_gallery_responsive-gallery-' . $key, array( $this, 'hide_metabox' ) );
2135
2136 add_meta_box( 'responsive-gallery-' . $key, sprintf( esc_html__( 'Gallery %s', 'responsive-lightbox' ), $args['label'] ), array( $this, 'add_metabox' ), 'rl_gallery', 'responsive_lightbox_metaboxes', 'high', $new_args );
2137 }
2138
2139 // side metaboxes
2140 add_meta_box( 'responsive-gallery-shortcode', esc_html__( 'Gallery Code', 'responsive-lightbox' ), array( $this, 'shortcode_metabox' ), 'rl_gallery', 'side', 'core' );
2141 }
2142
2143 /**
2144 * Add single metabox.
2145 *
2146 * @param object $post Post object
2147 * @param array $callback_args Arguments
2148 * @return void
2149 */
2150 public function add_metabox( $post, $callback_args ) {
2151 $html = $callback_args['args']['tab_id'] === 'images' ? '<input type="hidden" name="rl_active_tab" value="' . esc_attr( $callback_args['args']['active_tab'] ) . '" />' : '';
2152
2153 // default menu item
2154 $menu_item = 'options';
2155
2156 // get tab data
2157 $data = get_post_meta( $post->ID, '_rl_' . $callback_args['args']['tab_id'], true );
2158
2159 if ( ! is_array( $data ) )
2160 $data = [];
2161
2162 if ( $callback_args['args']['tab_id'] === 'design' && ! empty( $data['menu_item'] ) && is_array( $data[$data['menu_item']] ) ) {
2163 $design_data = $data[$data['menu_item']];
2164
2165 // remove show_title
2166 if ( isset( $design_data['show_title'] ) ) {
2167 if ( ! isset( $design_data['design_show_title'] ) )
2168 $design_data['design_show_title'] = $design_data['show_title'];
2169
2170 unset( $design_data['show_title'] );
2171 }
2172
2173 // remove show_caption
2174 if ( isset( $design_data['show_caption'] ) ) {
2175 if ( ! isset( $design_data['design_show_caption'] ) )
2176 $design_data['design_show_caption'] = $design_data['show_caption'];
2177
2178 unset( $design_data['show_caption'] );
2179 }
2180
2181 $data[$data['menu_item']] = $design_data;
2182 }
2183
2184 // maybe add description
2185 $html .= ! empty( $callback_args['args']['description'] ) ? '<p class="rl-gallery-tab-description">' . esc_html( $callback_args['args']['description'] ) . '</p>' : '';
2186
2187 // get main instance
2188 $rl = Responsive_Lightbox();
2189
2190 // maybe add menu
2191 if ( ! empty( $callback_args['args']['menu_items'] ) ) {
2192 // get selected menu item
2193 $menu_item = ! empty( $data['menu_item'] ) && in_array( $data['menu_item'], array_keys( $callback_args['args']['menu_items'] ) ) ? $data['menu_item'] : key( $callback_args['args']['menu_items'] );
2194
2195 $html .= '
2196 <div class="rl-gallery-tab-menu rl-gallery-tab-menu-' . esc_attr( $callback_args['args']['tab_id'] ) . '">';
2197
2198 foreach ( $callback_args['args']['menu_items'] as $menu_key => $menu_label ) {
2199 // disable select for remote library if needed
2200 if ( $menu_key === 'remote_library' && ! $rl->options['remote_library']['active'] ) {
2201 $title = __( 'Remote Library is disabled. Enable it in the settings.', 'responsive-lightbox' );
2202 $disabled = true;
2203 // disable select for media folders if needed
2204 } elseif ( $menu_key === 'folders' && ! $rl->options['folders']['active'] ) {
2205 $title = __( 'Media Folders are disabled. Enable it in the settings.', 'responsive-lightbox' );
2206 $disabled = true;
2207 // other menu items
2208 } else {
2209 $title = '';
2210 $disabled = false;
2211 }
2212
2213 $html .= '
2214 <label' . ( $title !== '' ? ' title="' . esc_attr( $title ). '"' : '' ) . '><input type="radio" class="rl-gallery-tab-menu-item" name="rl_gallery[' . esc_attr( $callback_args['args']['tab_id'] ) . '][menu_item]" value="' . esc_attr( $menu_key ) . '" ' . checked( $menu_item, $menu_key, false ) . ' ' . disabled( $disabled, true, false ) . ' />' . esc_html( $menu_label ) . ( $callback_args['args']['tab_id'] === 'config' && $menu_key === 'default' ? ' (' . esc_html( $this->tabs['config']['menu_items'][$rl->options['settings']['builder_gallery']] ) . ')' : '' ) . '</label>';
2215 }
2216
2217 $html .= '
2218 <span class="spinner" style="display: none;"></span>
2219 </div>';
2220 }
2221
2222 $class = '';
2223
2224 // disable gallery images content for remote library or media folders if needed
2225 if ( $callback_args['args']['tab_id'] === 'images' && ( ( $menu_item === 'remote_library' && ! $rl->options['remote_library']['active'] ) || ( $menu_item === 'folders' && ! $rl->options['folders']['active'] ) ) )
2226 $class = 'rl-loading-content';
2227
2228 $html .= '
2229 <div class="rl-gallery-tab-content rl-gallery-tab-content-' . esc_attr( $callback_args['args']['tab_id'] ) . ( $class !== '' ? ' ' . esc_attr( $class ) : '' ) . '">';
2230
2231 $html .= ! empty( $callback_args['args']['callback'] ) && is_callable( $callback_args['args']['callback'] ) ? call_user_func( $callback_args['args']['callback'], $callback_args['args']['tab_id'], $data, $menu_item, $post->ID ) : $this->get_metabox_content( $callback_args['args']['tab_id'], $data, $menu_item, $post->ID );
2232
2233 $html .= '
2234 </div>';
2235
2236 // get allowed html
2237 $allowed_html = wp_kses_allowed_html( 'post' );
2238
2239 $allowed_html['a']['disabled'] = [];
2240 $allowed_html['span']['data-select2-id'] = [];
2241 $allowed_html['input'] = [
2242 'type' => [],
2243 'name' => [],
2244 'value' => [],
2245 'class' => [],
2246 'id' => [],
2247 'size' => [],
2248 'checked' => [],
2249 'disabled' => [],
2250 'aria-describedby' => [],
2251 'min' => [],
2252 'max' => [],
2253 'step' => [],
2254 'data-default-color' => []
2255 ];
2256 $allowed_html['select'] = [
2257 'name' => [],
2258 'id' => [],
2259 'class' => [],
2260 'multiple' => [],
2261 'data-empty' => [],
2262 'data-type' => [],
2263 'aria-hidden' => []
2264 ];
2265 $allowed_html['option'] = [
2266 'value' => [],
2267 'selected' => [],
2268 'class' => []
2269 ];
2270 $allowed_html['optgroup'] = [
2271 'label' => []
2272 ];
2273
2274 add_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] );
2275
2276 echo wp_kses( $html, $allowed_html );
2277
2278 remove_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] );
2279 }
2280
2281 /**
2282 * Add new properties to style safe list.
2283 *
2284 * @param array $styles
2285 * @return array
2286 */
2287 public function allow_style_attributes( $styles ) {
2288 $styles[] = 'display';
2289 $styles[] = 'visibility';
2290
2291 return $styles;
2292 }
2293
2294 /**
2295 * Get single metabox content.
2296 *
2297 * @param string $tab_id Tab ID
2298 * @param array $data Metabox data
2299 * @param string $menu_item Specified menu item
2300 * @param int $gallery_id Gallery ID
2301 * @return string
2302 */
2303 public function get_metabox_content( $tab_id, $data, $menu_item, $gallery_id = 0 ) {
2304 $html = '
2305 <div class="rl-gallery-tab-inside rl-gallery-tab-inside-' . esc_attr( $tab_id ) . '-' . esc_attr( $menu_item ) . '">
2306 <table class="form-table">';
2307
2308 switch ( $tab_id ) {
2309 case 'config':
2310 // get main instance
2311 $rl = Responsive_Lightbox();
2312
2313 // get default gallery fields
2314 $default_gallery = $rl->frontend->get_default_gallery_fields();
2315
2316 // assign settings and defaults
2317 $settings = $rl->settings->settings;
2318 $defaults = $rl->defaults;
2319
2320 if ( ! array_key_exists( 'default_gallery', $settings ) )
2321 $settings['default_gallery']['fields'] = $default_gallery;
2322
2323 // assign default values
2324 foreach ( $default_gallery as $field => $field_args ) {
2325 $defaults['default_gallery'][$field] = $field_args['default'];
2326 }
2327
2328 // valid gallery?
2329 if ( array_key_exists( $menu_item . '_gallery', $settings ) && array_key_exists( $menu_item . '_gallery', $defaults ) ) {
2330 if ( $menu_item === 'default' )
2331 $fields = $settings['default_gallery']['fields'];
2332 else {
2333 $fields = $rl->frontend->get_unique_fields( $settings['default_gallery']['fields'], $settings[$menu_item . '_gallery']['fields'] );
2334
2335 // add default gallery default values
2336 foreach ( $default_gallery as $field => $field_args ) {
2337 $defaults[$menu_item . '_gallery'][$field] = $field_args['default'];
2338 }
2339 }
2340
2341 foreach ( $fields as $field => $args ) {
2342 if ( $args['type'] === 'multiple' ) {
2343 $new_args = $args;
2344
2345 foreach ( $args['fields'] as $subfield => $subargs ) {
2346 $new_args['fields'][$subfield] = $subargs + array(
2347 'value' => isset( $data[$menu_item], $data[$menu_item][$subfield] ) ? $data[$menu_item][$subfield] : $defaults[$menu_item . '_gallery'][$subfield],
2348 'default' => $defaults[$menu_item . '_gallery'][$subfield]
2349 );
2350 }
2351 } else {
2352 $new_args = $args + array(
2353 'value' => isset( $data[$menu_item], $data[$menu_item][$field] ) ? $data[$menu_item][$field] : $defaults[$menu_item . '_gallery'][$field],
2354 'default' => $defaults[$menu_item . '_gallery'][$field]
2355 );
2356 }
2357
2358 $html .= $this->render_field( $field, $tab_id, $menu_item, $new_args, $gallery_id );
2359 }
2360 // just in case ajax would fail
2361 } else
2362 $html .= '<p>' . esc_html__( 'No data', 'responsive-lightbox' ) . '</p>';
2363 break;
2364
2365 default:
2366 foreach ( $this->fields[$tab_id][$menu_item] as $field => $args ) {
2367 // was this field stored in a database?
2368 if ( isset( $args['save'] ) && ! $args['save'] )
2369 $new_args = $args;
2370 elseif ( $args['type'] === 'multiple' ) {
2371 $new_args = $args;
2372
2373 foreach ( $args['fields'] as $subfield => $subargs ) {
2374 $new_args['fields'][$subfield] = $subargs + array( 'value' => isset( $data[$menu_item], $data[$menu_item][$subfield] ) ? $data[$menu_item][$subfield] : $subargs['default'] );
2375 }
2376 } else
2377 $new_args = $args + array( 'value' => isset( $data[$menu_item], $data[$menu_item][$field] ) ? $data[$menu_item][$field] : $args['default'] );
2378
2379 // media preview?
2380 // if ( $tab_id === 'images' && $menu_item === 'featured' && $field === 'attachments' && $args['type'] === 'media_preview' )
2381 // $new_args['subfields'] = $data['featured'];
2382
2383 $html .= $this->render_field( $field, $tab_id, $menu_item, $new_args, $gallery_id );
2384 }
2385 }
2386
2387 $html .= '
2388 </table>
2389 </div>';
2390
2391 return apply_filters( 'rl_gallery_tab_content', $html, $tab_id, $data, $menu_item );
2392 }
2393
2394 /**
2395 * Update number of gallery images when attachment is deleted.
2396 *
2397 * @param int $attachment_id
2398 * @return void
2399 */
2400 public function delete_attachment( $attachment_id ) {
2401 //@TODO
2402 }
2403
2404 /**
2405 * Get number of gallery images.
2406 *
2407 * @param int $gallery_id
2408 * @return int
2409 */
2410 public function get_gallery_images_number( $gallery_id ) {
2411 return count( $this->get_gallery_images( $gallery_id, [ 'count_images' => true, 'preview' => false, 'exclude' => true ] ) );
2412 }
2413
2414 /**
2415 * Get gallery images.
2416 *
2417 * @global string $pagenow
2418 *
2419 * @param int $gallery_id Gallery ID
2420 * @param array $args Gallery arguments
2421 * @return array
2422 */
2423 public function get_gallery_images( $gallery_id = 0, $args = [] ) {
2424 $images = [];
2425 $excluded = [];
2426
2427 // get main instance
2428 $rl = Responsive_Lightbox();
2429
2430 // get args
2431 $defaults = array(
2432 'count_images' => false,
2433 'exclude' => false,
2434 'posts_per_page' => -1,
2435 'images_per_page' => 0,
2436 'page' => 1,
2437 'limit' => 0,
2438 'nopaging' => true,
2439 'image_size' => 'large',
2440 'thumbnail_size' => 'thumbnail',
2441 'pagination_type' => 'paged',
2442 'pagination_position' => 'bottom',
2443 'orderby' => 'menu_order',
2444 'order' => 'asc',
2445 'preview' => is_admin(),
2446 'preview_type' => 'update',
2447 'preview_page' => 1,
2448 'preview_per_page' => 20,
2449 'taxonomy' => $rl->options['folders']['media_taxonomy'],
2450 'folder' => array(
2451 'id' => 0,
2452 'children' => null // do not change!
2453 )
2454 );
2455
2456 // parse arguments
2457 $args = wp_parse_args( apply_filters( 'rl_get_gallery_images_args', $args, $gallery_id ), $defaults );
2458
2459 // disable counting mode
2460 if ( $args['preview'] )
2461 $args['count_images'] = false;
2462
2463 // sanitize args
2464 $args['exclude'] = (bool) ! empty( $args['exclude'] );
2465 $args['posts_per_page'] = ! empty( $args['posts_per_page'] ) ? (int) $args['posts_per_page'] : -1;
2466 $args['nopaging'] = (bool) ! empty( $args['nopaging'] );
2467
2468 // check gallery post type
2469 $valid_gallery_type = ( get_post_type( $gallery_id ) === 'rl_gallery' );
2470
2471 // is it rl_gallery? skip when counting mode is enabled
2472 if ( $valid_gallery_type && ! $args['count_images'] ) {
2473 $paging = get_post_meta( $gallery_id, '_rl_paging', true );
2474
2475 if ( isset( $paging['menu_item'] ) ) {
2476 $pagination = $paging[$paging['menu_item']];
2477
2478 if ( $pagination['pagination'] ) {
2479 $args['nopaging'] = false;
2480 $args['images_per_page'] = $pagination['images_per_page'];
2481 $args['pagination_type'] = $pagination['pagination_type'];
2482
2483 // infinite type?
2484 if ( $args['pagination_type'] === 'infinite' )
2485 $args['pagination_position'] = 'bottom';
2486 else
2487 $args['pagination_position'] = $pagination['pagination_position'];
2488 } else
2489 $args['nopaging'] = true;
2490 }
2491 }
2492
2493 global $pagenow;
2494
2495 // is it preview?
2496 if ( ( in_array( $pagenow, array( 'post.php', 'post-new.php' ), true ) && $gallery_id ) || ( isset( $_POST['action'] ) && $_POST['action'] === 'rl-get-preview-content' ) || ( wp_doing_ajax() && isset( $_POST['action'] ) && ( $_POST['action'] === 'rl-post-gallery-preview' || $_POST['action'] === 'rl-get-menu-content' ) ) )
2497 $args['images_per_page'] = 0;
2498
2499 if ( isset( $_GET['rl_page'] ) )
2500 $args['page'] = (int) $_GET['rl_page'];
2501 else
2502 $args['page'] = (int) $args['page'];
2503
2504 // is it rl_gallery?
2505 if ( $valid_gallery_type ) {
2506 // no need order in counting mode
2507 if ( ! $args['count_images'] ) {
2508 // get config metadata
2509 $config_meta = get_post_meta( $gallery_id, '_rl_config', true );
2510
2511 // config order
2512 if ( isset( $config_meta['menu_item'] ) ) {
2513 $config = $config_meta[$config_meta['menu_item']];
2514
2515 $args['orderby'] = $config['orderby'];
2516 $args['order'] = $config['order'];
2517 }
2518 }
2519
2520 // get images metadata
2521 $data = get_post_meta( $gallery_id, '_rl_images', true );
2522
2523 // array?
2524 if ( ! is_array( $data ) )
2525 $data = [];
2526
2527 // get menu item
2528 if ( ! empty( $this->menu_item ) )
2529 $menu_item = $this->menu_item;
2530 elseif ( array_key_exists( 'menu_item', $data ) )
2531 $menu_item = $data['menu_item'];
2532 else
2533 $menu_item = 'media';
2534
2535 // valid data?
2536 if ( ! array_key_exists( $menu_item, $data ) )
2537 $data[$menu_item] = [];
2538
2539 if ( $args['preview'] && $this->fields['images'][$menu_item]['attachments']['preview']['pagination'] ) {
2540 if ( isset( $args['preview_page'] ) )
2541 $args['preview_page'] = (int) $args['preview_page'];
2542 else
2543 $args['preview_page'] = 1;
2544
2545 $args['preview_per_page'] = (int) $args['preview_per_page'];
2546 }
2547
2548 switch ( $menu_item ) {
2549 case 'media':
2550 // check embed data
2551 if ( ! empty( $data[$menu_item]['attachments']['embed'] ) ) {
2552 $atts_args = [
2553 'embed_keys' => array_keys( $data[$menu_item]['attachments']['embed'] ),
2554 'providers' => [ 'youtube', 'vimeo' ]
2555 ];
2556 } else
2557 $atts_args = [];
2558
2559 // get attachment ids
2560 $attachments = ! empty( $data[$menu_item]['attachments']['ids'] ) ? $this->check_attachments( array_unique( array_filter( $data[$menu_item]['attachments']['ids'] ) ), $atts_args ) : [];
2561
2562 // filter attachments
2563 $attachments = apply_filters( 'rl_get_gallery_images_attachments', $attachments, $atts_args );
2564
2565 // exclude any attachments?
2566 if ( $args['exclude'] && ! empty( $data[$menu_item]['attachments']['exclude'] ) )
2567 $attachments = array_diff( $attachments, $data[$menu_item]['attachments']['exclude'] );
2568
2569 // check filtered attachments
2570 $attachments = $this->check_attachments( $attachments, $atts_args );
2571
2572 // any attachments?
2573 if ( $attachments ) {
2574 if ( $args['limit'] )
2575 $counter = 0;
2576
2577 foreach ( $attachments as $attachment_id ) {
2578 // for counting mode get attachment id only
2579 if ( $args['count_images'] )
2580 $images[] = $attachment_id;
2581 else {
2582 // embed?
2583 if ( preg_match( '/^e\d+$/', $attachment_id ) === 1 ) {
2584 $attachment_data = $data[$menu_item]['attachments']['embed'][$attachment_id];
2585 $attachment_data['type'] = 'embed';
2586 } else
2587 $attachment_data = $attachment_id;
2588
2589 // get attachment image data
2590 $images[] = $this->get_gallery_image_src( $attachment_data, $args['image_size'], $args['thumbnail_size'] );
2591
2592 // limit attachments?
2593 if ( $args['limit'] ) {
2594 $counter++;
2595
2596 // limit reached?
2597 if ( $counter === $args['limit'] )
2598 break;
2599 }
2600 }
2601 }
2602 }
2603 break;
2604
2605 case 'featured':
2606 // only for featured frontend galleries
2607 if ( ! is_admin() || wp_doing_ajax() ) {
2608 // prepare featured fields
2609 $this->fields['images']['featured'] = $this->prepare_featured_fields( $this->fields['images']['featured'] );
2610 }
2611
2612 // copy arguments
2613 $query_args = $args;
2614
2615 // skip order for counting mode
2616 if ( ! $args['count_images'] ) {
2617 // prevent duplicating images order (config tab) with posts order (images tab), query will handle empty strings
2618 if ( array_key_exists( 'post_orderby', $args ) )
2619 $query_args['orderby'] = $args['post_orderby'];
2620 elseif ( array_key_exists( 'orderby', $data[$menu_item] ) )
2621 $query_args['orderby'] = $data[$menu_item]['orderby'];
2622 else
2623 $query_args['orderby'] = '';
2624
2625 if ( array_key_exists( 'post_order', $args ) )
2626 $query_args['order'] = $args['post_order'];
2627 elseif ( array_key_exists( 'order', $data[$menu_item] ) )
2628 $query_args['order'] = $data[$menu_item]['order'];
2629 else
2630 $query_args['order'] = '';
2631 }
2632
2633 // get attachment ids
2634 $attachments = $this->gallery_query( array_merge( $data[$menu_item], $query_args ) );
2635
2636 // filter attachments
2637 $attachments = apply_filters( 'rl_get_gallery_images_attachments', $attachments );
2638
2639 // exclude any attachments?
2640 if ( $args['exclude'] && ! empty( $data[$menu_item]['attachments']['exclude'] ) )
2641 $attachments = array_diff( $attachments, $data[$menu_item]['attachments']['exclude'] );
2642
2643 // any attachments?
2644 if ( $attachments ) {
2645 if ( $args['limit'] )
2646 $counter = 0;
2647
2648 foreach ( $attachments as $attachment_id ) {
2649 // real attachment?
2650 if ( ! wp_attachment_is_image( $attachment_id ) )
2651 continue;
2652
2653 // for counting mode get attachment id only
2654 if ( $args['count_images'] )
2655 $images[] = $attachment_id;
2656 else {
2657 // get attachment image data
2658 $images[] = $this->get_gallery_image_src( $attachment_id, $args['image_size'], $args['thumbnail_size'] );
2659
2660 // limit attachments?
2661 if ( $args['limit'] ) {
2662 $counter++;
2663
2664 // limit reached?
2665 if ( $counter === $args['limit'] )
2666 break;
2667 }
2668 }
2669 }
2670 }
2671 break;
2672
2673 case 'folders':
2674 // is folders active?
2675 if ( ! $rl->options['folders']['active'] )
2676 break;
2677
2678 if ( ! array_key_exists( 'folder', $data[$menu_item] ) )
2679 $data[$menu_item]['folder'] = $defaults['folder'];
2680
2681 // ajax requests
2682 if ( is_string( $args['folder']['id'] ) )
2683 $args['folder']['id'] = (int) $args['folder']['id'];
2684
2685 // not empty folder term id?
2686 if ( ! empty( $args['folder']['id'] ) ) {
2687 // get term
2688 $term = get_term( $args['folder']['id'], $args['taxonomy'] );
2689
2690 // valid term?
2691 if ( is_a( $term, 'WP_Term' ) )
2692 $folder_id = (int) $term->term_id;
2693 else
2694 $folder_id = (int) $data[$menu_item]['folder']['id'];
2695 } else {
2696 if ( isset( $_POST['action'] ) && $_POST['action'] === 'rl-get-preview-content' )
2697 $folder_id = $args['folder']['id'];
2698 else
2699 $folder_id = (int) $data[$menu_item]['folder']['id'];
2700 }
2701
2702 if ( $folder_id >= 0 ) {
2703 $include_children = false;
2704
2705 // null means folder was not changed
2706 if ( $args['folder']['children'] === null ) {
2707 if ( array_key_exists( 'children', $data[$menu_item]['folder'] ) && $data[$menu_item]['folder']['children'] === true )
2708 $include_children = true;
2709 // overwritten by args
2710 } else {
2711 if ( is_string( $args['folder']['children'] ) ) {
2712 if ( $args['folder']['children'] === 'true' )
2713 $include_children = true;
2714 } elseif ( is_bool( $args['folder']['children'] ) ) {
2715 if ( $args['folder']['children'] )
2716 $include_children = true;
2717 }
2718 }
2719
2720 if ( $folder_id === 0 ) {
2721 if ( $include_children ) {
2722 $all_folders = get_terms(
2723 array(
2724 'taxonomy' => $args['taxonomy'],
2725 'hide_empty' => false,
2726 'fields' => 'ids',
2727 'hierarchical' => false,
2728 'number' => 0
2729 )
2730 );
2731
2732 $tax_query = array(
2733 array(
2734 'relation' => 'OR',
2735 array(
2736 'taxonomy' => $args['taxonomy'],
2737 'field' => 'term_id',
2738 'terms' => ( ! is_wp_error( $all_folders ) ) ? $all_folders : $folder_id,
2739 'include_children' => $include_children,
2740 'operator' => 'IN'
2741 ),
2742 array(
2743 'taxonomy' => $args['taxonomy'],
2744 'field' => 'term_id',
2745 'terms' => $folder_id,
2746 'include_children' => $include_children,
2747 'operator' => 'NOT EXISTS'
2748 )
2749 )
2750 );
2751 } else {
2752 $tax_query = array(
2753 array(
2754 'taxonomy' => $args['taxonomy'],
2755 'field' => 'term_id',
2756 'terms' => $folder_id,
2757 'include_children' => $include_children,
2758 'operator' => 'NOT EXISTS'
2759 )
2760 );
2761 }
2762 } else {
2763 $tax_query = array(
2764 array(
2765 'taxonomy' => $args['taxonomy'],
2766 'field' => 'term_id',
2767 'terms' => $folder_id,
2768 'include_children' => $include_children,
2769 'operator' => 'IN'
2770 )
2771 );
2772 }
2773
2774 // prepare query arguments
2775 $wp_query_args = array(
2776 'post_type' => 'attachment',
2777 'post_status' => 'inherit',
2778 'post_mime_type' => array( 'image/jpeg', 'image/gif', 'image/png' ),
2779 'nopaging' => true,
2780 'posts_per_page' => -1,
2781 'fields' => 'ids',
2782 'tax_query' => $tax_query
2783 );
2784
2785 // is it preview?
2786 if ( $args['preview'] ) {
2787 $wp_query_args['posts_per_page'] = $args['preview_per_page'];
2788 $wp_query_args['offset'] = ( $args['preview_page'] - 1 ) * $args['preview_per_page'];
2789 $wp_query_args['nopaging'] = false;
2790 }
2791
2792 // run query
2793 $query = new WP_Query( apply_filters( 'rl_folders_query_args', $wp_query_args ) );
2794
2795 // get attachment ids
2796 $attachments = $query->get_posts();
2797
2798 // valid attachments?
2799 if ( ! is_wp_error( $attachments ) ) {
2800 // cast ids to int
2801 $attachments = array_map( 'intval', $attachments );
2802
2803 // make sure to skip duplicates
2804 $attachments = array_unique( $attachments );
2805
2806 // filter attachments
2807 $attachments = apply_filters( 'rl_get_gallery_images_attachments', $attachments );
2808
2809 // exclude any attachments?
2810 if ( $args['exclude'] && ! empty( $data[$menu_item]['attachments']['exclude'] ) )
2811 $attachments = array_diff( $attachments, $data[$menu_item]['attachments']['exclude'] );
2812
2813 // any attachments?
2814 if ( $attachments ) {
2815 if ( $args['limit'] )
2816 $counter = 0;
2817
2818 foreach ( $attachments as $attachment_id ) {
2819 // real attachment?
2820 if ( ! wp_attachment_is_image( $attachment_id ) )
2821 continue;
2822
2823 // for counting mode get attachment id only
2824 if ( $args['count_images'] )
2825 $images[] = $attachment_id;
2826 else {
2827 // get attachment image data
2828 $images[] = $this->get_gallery_image_src( $attachment_id, $args['image_size'], $args['thumbnail_size'] );
2829
2830 // limit attachments?
2831 if ( $args['limit'] ) {
2832 $counter++;
2833
2834 // limit reached?
2835 if ( $counter === $args['limit'] )
2836 break;
2837 }
2838 }
2839 }
2840 }
2841 }
2842 }
2843 break;
2844
2845 case 'remote_library':
2846 // is remote library active?
2847 if ( ! $rl->options['remote_library']['active'] )
2848 break;
2849
2850 // no media search phrase?
2851 if ( ! isset( $args['media_search'] ) )
2852 $args['media_search'] = isset( $data[$menu_item]['media_search'] ) ? $data[$menu_item]['media_search'] : '';
2853
2854 // no media provider?
2855 if ( ! isset( $args['media_provider'] ) )
2856 $args['media_provider'] = isset( $data[$menu_item]['media_provider'] ) ? $data[$menu_item]['media_provider'] : 'all';
2857
2858 // get remote images
2859 $images = $rl->remote_library->get_remote_library_images( $args );
2860 break;
2861 }
2862 }
2863
2864 // skip order for counting mode
2865 if ( ! $args['count_images'] ) {
2866 // config sort order
2867 switch ( $args['orderby'] ) {
2868 case 'id':
2869 $sort = [];
2870
2871 foreach ( $images as $key => $image ) {
2872 // set sorting value
2873 $sort[$key] = $image['id'];
2874 }
2875
2876 // sort
2877 array_multisort( $sort, $args['order'] === 'asc' ? SORT_ASC : SORT_DESC, SORT_NUMERIC, $images );
2878 break;
2879
2880 case 'title':
2881 $sort = [];
2882
2883 if ( $valid_gallery_type ) {
2884 // get lightbox data
2885 $lightbox_meta = get_post_meta( $gallery_id, '_rl_lightbox', true );
2886
2887 // valid data?
2888 if ( isset( $lightbox_meta['menu_item'] ) )
2889 $title_arg = $lightbox_meta[$lightbox_meta['menu_item']]['lightbox_image_title'];
2890 else
2891 $title_arg = $rl->options['settings']['gallery_image_title'];
2892 } else
2893 $title_arg = $rl->options['settings']['gallery_image_title'];
2894
2895 $images_copy = $images;
2896
2897 foreach ( $images_copy as $key => $image ) {
2898 if ( $title_arg === 'global' )
2899 $images[$key]['title'] = $rl->frontend->get_attachment_title( $image['id'], $rl->options['settings']['gallery_image_title'] );
2900 elseif ( $title_arg === 'default' )
2901 $images[$key]['title'] = '';
2902 else
2903 $images[$key]['title'] = $rl->frontend->get_attachment_title( $image['id'], $title_arg );
2904
2905 // set sorting value
2906 $sort[$key] = function_exists( 'mb_strtolower' ) ? mb_strtolower( $images[$key]['title'] ) : strtolower( $images[$key]['title'] );
2907 }
2908
2909 // sort
2910 array_multisort( $sort, $args['order'] === 'asc' ? SORT_ASC : SORT_DESC, SORT_STRING, $images );
2911 break;
2912
2913 case 'post_date':
2914 $sort = [];
2915
2916 foreach ( $images as $key => $image ) {
2917 // set sorting value
2918 $sort[$key] = $image['date'];
2919 }
2920
2921 // sort
2922 array_multisort( $sort, $args['order'] === 'asc' ? SORT_ASC : SORT_DESC, $images );
2923 break;
2924
2925 case 'menu_order':
2926 // do nothing
2927 break;
2928
2929 case 'rand':
2930 shuffle( $images );
2931 break;
2932 }
2933 }
2934
2935 // filter images
2936 $images = apply_filters( 'rl_get_gallery_images_array', $images, $gallery_id, $args );
2937
2938 // count number of images
2939 $images_count = count( $images );
2940
2941 // no preview?
2942 if ( ! $args['preview'] && ! $args['count_images'] && $args['limit'] === 0 )
2943 update_post_meta( $gallery_id, '_rl_images_count', $images_count );
2944
2945 // images pagination?
2946 if ( $images && ! $args['nopaging'] && $args['images_per_page'] > 0 && ! $args['count_images'] ) {
2947 // get part of images
2948 $images = array_slice( $images, ( $args['page'] - 1 ) * $args['images_per_page'], $args['images_per_page'], true );
2949
2950 // pass gallery args
2951 $this->gallery_args = $args;
2952 $this->gallery_args['total'] = (int) ceil( $images_count / $args['images_per_page'] );
2953
2954 // remove actions to avoid issues with multiple galleries on single page
2955 remove_action( 'rl_before_gallery', [ $this, 'do_pagination' ], 10 );
2956 remove_action( 'rl_after_gallery', [ $this, 'do_pagination' ], 10 );
2957
2958 // pagination position
2959 if ( $args['pagination_position'] === 'top' )
2960 add_action( 'rl_before_gallery', [ $this, 'do_pagination' ], 10, 2 );
2961 elseif ( $args['pagination_position'] === 'bottom' )
2962 add_action( 'rl_after_gallery', [ $this, 'do_pagination' ], 10, 2 );
2963 else {
2964 add_action( 'rl_before_gallery', [ $this, 'do_pagination' ], 10, 2 );
2965 add_action( 'rl_after_gallery', [ $this, 'do_pagination' ], 10, 2 );
2966 }
2967 }
2968
2969 return apply_filters( 'rl_get_gallery_images', array_values( $images ), $gallery_id, $args );
2970 }
2971
2972 /**
2973 * Create gallery pagination.
2974 *
2975 * @global object $wp
2976 *
2977 * @param array $args
2978 * @param int $gallery_id
2979 * @return void
2980 */
2981 public function do_pagination( $args, $gallery_id ) {
2982 global $wp;
2983
2984 // get main instance
2985 $rl = Responsive_Lightbox();
2986
2987 // get current action
2988 $current_action = current_action();
2989
2990 if ( $current_action === 'rl_before_gallery' )
2991 $class = 'rl-pagination-top';
2992 elseif ( $current_action === 'rl_after_gallery' )
2993 $class = 'rl-pagination-bottom';
2994 else
2995 $class = '';
2996
2997 // set base arguments
2998 $base_args = [ 'rl_gallery_no' => $rl->frontend->get_data( 'gallery_no' ), 'rl_page' => '%#%' ];
2999
3000 if ( empty( $args['pagination_type'] ) )
3001 $args['pagination_type'] = 'paged';
3002
3003 // infinite scroll?
3004 if ( $args['pagination_type'] === 'infinite' )
3005 $base_args['rl_lightbox_script'] = $rl->get_data( 'current_script' );
3006
3007 echo
3008 '<div class="rl-pagination ' . esc_attr( $class ) . '"' . ( $args['pagination_type'] === 'infinite' ? ' data-button="' . esc_attr( $args['load_more'] ) . '"' : '' ) .'>' .
3009 paginate_links(
3010 [
3011 'format' => '?rl_page=%#%',
3012 'base' => add_query_arg( $base_args, $args['pagination_type'] !== 'paged' ? get_permalink( $gallery_id ) : home_url( $wp->request ) ),
3013 'total' => $this->gallery_args['total'],
3014 'current' => $this->gallery_args['page'],
3015 'show_all' => false,
3016 'end_size' => 1,
3017 'mid_size' => 2,
3018 'prev_next' => true,
3019 'prev_text' => esc_html__( '&laquo; Previous', 'responsive-lightbox' ),
3020 'next_text' => esc_html__( 'Next &raquo;', 'responsive-lightbox' ),
3021 'type' => 'plain',
3022 'add_args' => '',
3023 'add_fragment' => '',
3024 'before_page_number' => '',
3025 'after_page_number' => ''
3026 ]
3027 ) .
3028 '</div>' . ( $args['pagination_type'] === 'infinite' && $args['load_more'] === 'manually' ? '<div class="rl-gallery-button"><button class="rl-button rl-load-more">' . esc_html__( 'Load more', 'responsive-lightbox' ) . '</button></div>' : '' );
3029 }
3030
3031 /**
3032 * Check whether is it valid gallery AJAX request (rl-get-gallery-page-content action).
3033 *
3034 * @return bool
3035 */
3036 public function gallery_ajax_verified() {
3037 return ( wp_doing_ajax() && isset( $_POST['action'], $_POST['gallery_id'], $_POST['gallery_no'], $_POST['page'], $_POST['nonce'], $_POST['preview'], $_POST['post_id'], $_POST['lightbox'] ) && $_POST['action'] === 'rl-get-gallery-page-content' && wp_verify_nonce( $_POST['nonce'], 'rl_nonce' ) );
3038 }
3039
3040 /**
3041 * Try to change lightbox in valid gallery AJAX request (rl-get-gallery-page-content action).
3042 *
3043 * @return void
3044 */
3045 public function maybe_change_lightbox() {
3046 // check whether is it valid gallery ajax request
3047 if ( $this->gallery_ajax_verified() ) {
3048 // set new lightbox script
3049 Responsive_Lightbox()->set_lightbox_script( sanitize_key( $_POST['lightbox'] ) );
3050 }
3051 }
3052
3053 /**
3054 * Get gallery page.
3055 *
3056 * @param array $args
3057 * @return void
3058 */
3059 public function get_gallery_page( $args ) {
3060 // check whether is it valid gallery ajax request
3061 if ( $this->gallery_ajax_verified() ) {
3062 // cast page number
3063 $_GET['rl_page'] = (int) $_POST['page'];
3064
3065 // check preview
3066 $preview = ( $_POST['preview'] === 'true' );
3067
3068 echo $this->gallery_shortcode(
3069 [
3070 'id' => (int) $_POST['gallery_id'],
3071 'gallery_no' => (int) $_POST['gallery_no'],
3072 'preview' => $preview
3073 ]
3074 );
3075 }
3076
3077 exit;
3078 }
3079
3080 /**
3081 * Generate gallery preview.
3082 *
3083 * @return void
3084 */
3085 public function post_gallery_preview() {
3086 // check data
3087 if ( ! isset( $_POST['post_id'], $_POST['gallery_id'], $_POST['nonce'], $_POST['page'] ) || ! check_ajax_referer( 'rl-gallery-post', 'nonce', false ) )
3088 wp_send_json_error();
3089
3090 // check page
3091 $page = preg_replace( '/[^a-z-.]/i', '', $_POST['page'] );
3092
3093 // check page
3094 if ( ! in_array( $page, [ 'widgets.php', 'customize.php', 'post.php', 'post-new.php' ], true ) )
3095 wp_send_json_error();
3096
3097 // check edit_post capability
3098 if ( ( $page === 'post.php' || $page === 'post-new.php' ) && ! current_user_can( 'edit_post', (int) $_POST['post_id'] ) )
3099 wp_send_json_error();
3100
3101 // check edit_theme_options capability
3102 if ( ( $page === 'widgets.php' || $page === 'customize.php' ) && ! current_user_can( 'edit_theme_options' ) )
3103 wp_send_json_error();
3104
3105 // parse gallery id
3106 $gallery_id = (int) $_POST['gallery_id'];
3107
3108 // get gallery data
3109 $data = get_post_meta( $gallery_id, '_rl_images', true );
3110
3111 // prepare data
3112 $attachments = $exclude = [];
3113 $html = '';
3114
3115 // get images
3116 $images = $this->get_gallery_images(
3117 $gallery_id,
3118 [
3119 'exclude' => true,
3120 'limit' => 20
3121 ]
3122 );
3123
3124 // get number of images
3125 $images_count = (int) get_post_meta( $gallery_id, '_rl_images_count', true );
3126
3127 if ( ! empty( $images ) ) {
3128 foreach ( $images as $image ) {
3129 $html .= '
3130 <li tabindex="0" role="checkbox" aria-label="' . esc_attr( $image['title'] ) . '" aria-checked="true" data-id="' . esc_attr( $image['id'] ) . '" class="attachment selection selected rl-status-active">
3131 <div class="attachment-preview js--select-attachment type-image ' . esc_attr( $image['thumbnail_orientation'] ). '">
3132 <div class="thumbnail">
3133 <div class="centered">
3134 <img src="' . esc_url( $image['thumbnail_url'] ) . '" draggable="false" alt="" />
3135 </div>
3136 </div>
3137 </div>
3138 </li>';
3139 }
3140 }
3141
3142 // send attachments content
3143 wp_send_json_success(
3144 array(
3145 'attachments' => $html,
3146 'count' => esc_html( sprintf( _n( '%s image', '%s images', $images_count, 'responsive-lightbox' ), $images_count ) ),
3147 'edit_url' => current_user_can( 'edit_post', $gallery_id ) ? esc_url_raw( admin_url( 'post.php?post=' . $gallery_id . '&action=edit' ) ) : ''
3148 )
3149 );
3150 }
3151
3152 /**
3153 * Get all galleries.
3154 *
3155 * @return void
3156 */
3157 public function post_get_galleries() {
3158 // check data
3159 if ( ! isset( $_POST['post_id'], $_POST['search'], $_POST['nonce'], $_POST['page'] ) || ! check_ajax_referer( 'rl-gallery-post', 'nonce', false ) )
3160 wp_send_json_error();
3161
3162 // check page
3163 $page = preg_replace( '/[^a-z-.]/i', '', $_POST['page'] );
3164
3165 // check page
3166 if ( ! in_array( $page, [ 'widgets.php', 'customize.php', 'post.php', 'post-new.php' ], true ) )
3167 wp_send_json_error();
3168
3169 // check edit_post capability
3170 if ( ( $page === 'post.php' || $page === 'post-new.php' ) && ! current_user_can( 'edit_post', (int) $_POST['post_id'] ) )
3171 wp_send_json_error();
3172
3173 // check edit_theme_options capability
3174 if ( ( $page === 'widgets.php' || $page === 'customize.php' ) && ! current_user_can( 'edit_theme_options' ) )
3175 wp_send_json_error();
3176
3177 $args = array(
3178 'post_type' => 'rl_gallery',
3179 'post_status' => 'publish',
3180 'nopaging' => true,
3181 'posts_per_page' => -1,
3182 'orderby' => 'title',
3183 'order' => 'ASC',
3184 'suppress_filters' => false,
3185 'no_found_rows' => true,
3186 'cache_results' => false
3187 );
3188
3189 // check category
3190 $category = isset( $_POST['category'] ) ? (int) $_POST['category'] : 0;
3191
3192 // specific category?
3193 if ( ! empty( $category ) ) {
3194 $args['tax_query'] = array(
3195 array(
3196 'taxonomy' => 'rl_category',
3197 'field' => 'term_id',
3198 'operator' => 'IN',
3199 'include_children' => false,
3200 'terms' => $category
3201 )
3202 );
3203 }
3204
3205 $search = wp_unslash( trim( $_POST['search'] ) );
3206
3207 if ( $search !== '' )
3208 $args['s'] = $search;
3209
3210 // get galleries
3211 $query = new WP_Query( $args );
3212
3213 $html = '';
3214 $ids = [];
3215
3216 // any galleries?
3217 if ( ! empty( $query->posts ) ) {
3218 foreach ( $query->posts as $gallery ) {
3219 // save gallery id
3220 $ids[] = (int) $gallery->ID;
3221
3222 // get featured image
3223 $featured = $this->get_featured_image_src( $gallery->ID );
3224
3225 if ( is_array( $featured ) && array_key_exists( 'url', $featured ) )
3226 $featured_image = $featured['url'];
3227 else
3228 $featured_image = '';
3229
3230 // get title
3231 $title = $gallery->post_title !== '' ? $gallery->post_title : esc_html__( '(no title)', 'responsive-gallery' );
3232
3233 $html .= '
3234 <li tabindex="0" role="checkbox" aria-label="' . esc_attr( $title ) . '" aria-checked="true" data-id="' . (int) $gallery->ID . '" class="attachment selection">
3235 <div class="attachment-preview js--select-attachment type-image ' . ( ! empty( $featured['thumbnail_orientation'] ) ? esc_attr( $featured['thumbnail_orientation'] ) : 'landscape' ) . '">
3236 <div class="thumbnail">
3237 <div class="centered" data-full-src="' . esc_url( $featured_image ) . '">
3238 ' . $this->get_featured_image( $gallery->ID, 'thumbnail' ) . '
3239 </div>
3240 <div class="filename">
3241 <div>' . esc_html( $title ) . '</div>
3242 </div>
3243 </div>
3244 </div>
3245 <button type="button" class="button-link check"><span class="media-modal-icon"></span><span class="screen-reader-text">' . esc_html__( 'Deselect', 'responsive-lightbox' ) . '</span></button>
3246 </li>';
3247 }
3248 }
3249
3250 // send galleries content
3251 wp_send_json_success(
3252 [
3253 'galleries' => $ids,
3254 'html' => $html
3255 ]
3256 );
3257 }
3258
3259 /**
3260 * Get gallery content based on request.
3261 *
3262 * @return void
3263 */
3264 public function get_menu_content() {
3265 if ( ! isset( $_POST['post_id'], $_POST['tab'], $_POST['menu_item'], $_POST['nonce'] ) || ! check_ajax_referer( 'rl-gallery', 'nonce', false ) )
3266 wp_send_json_error();
3267
3268 // check tab
3269 $tab = isset( $_POST['tab'] ) ? sanitize_key( $_POST['tab'] ) : '';
3270
3271 if ( ! array_key_exists( $tab, $this->tabs ) )
3272 wp_send_json_error();
3273
3274 // get post id
3275 $post_id = (int) $_POST['post_id'];
3276
3277 if ( ! current_user_can( 'edit_post', $post_id ) )
3278 wp_send_json_error();
3279
3280 // check menu item
3281 $menu_item = sanitize_key( $_POST['menu_item'] );
3282
3283 // get selected menu item
3284 $menu_item = ! empty( $menu_item ) && in_array( $menu_item, array_keys( $this->tabs[$tab]['menu_items'] ) ) ? $menu_item : key( $this->tabs[$tab]['menu_items'] );
3285
3286 // get tab content
3287 wp_send_json_success( $this->get_metabox_content( $tab, get_post_meta( $post_id, '_rl_' . $tab, true ), $menu_item, $post_id ) );
3288 }
3289
3290 /**
3291 * Get gallery preview content based on request.
3292 *
3293 * @return void
3294 */
3295 public function get_gallery_preview_content() {
3296 // initial checks
3297 if ( ! isset( $_POST['post_id'], $_POST['menu_item'], $_POST['nonce'], $_POST['preview_type'] ) || ! check_ajax_referer( 'rl-gallery', 'nonce', false ) )
3298 wp_send_json_error();
3299
3300 // cast gallery ID
3301 $post_id = (int) $_POST['post_id'];
3302
3303 // check user privileges
3304 if ( ! current_user_can( 'edit_post', $post_id ) || ! current_user_can( 'upload_files' ) )
3305 wp_send_json_error();
3306
3307 // get query args
3308 $args = ! empty( $_POST['query'] ) ? wp_unslash( $_POST['query'] ) : [];
3309
3310 // check orderby
3311 if ( array_key_exists( 'orderby', $args ) ) {
3312 $args['post_orderby'] = $args['orderby'];
3313
3314 unset( $args['orderby'] );
3315 }
3316
3317 // check order
3318 if ( array_key_exists( 'order', $args ) ) {
3319 $args['post_order'] = $args['order'];
3320
3321 unset( $args['order'] );
3322 }
3323
3324 // check preview type
3325 $preview_type = sanitize_key( $_POST['preview_type'] );
3326
3327 // check preview type
3328 if ( ! in_array( $preview_type, [ 'page', 'update' ], true ) )
3329 $args['preview_type'] = 'page';
3330 else
3331 $args['preview_type'] = $preview_type;
3332
3333 // check menu item
3334 $menu_item = sanitize_key( $_POST['menu_item'] );
3335
3336 // set images menu item
3337 $menu_item = $this->menu_item = ! empty( $menu_item ) && array_key_exists( $menu_item, $this->tabs['images']['menu_items'] ) ? $menu_item : 'media';
3338
3339 if ( $this->fields['images'][$menu_item]['attachments']['preview']['pagination'] ) {
3340 if ( isset( $args['preview_page'] ) )
3341 $args['preview_page'] = (int) $args['preview_page'];
3342 else
3343 $args['preview_page'] = 1;
3344 }
3345
3346 // get images
3347 $images = $this->get_gallery_images( $post_id, $args );
3348
3349 // prepare JSON array
3350 $data = [];
3351
3352 if ( $menu_item === 'remote_library' ) {
3353 // get main instance
3354 $rl = Responsive_Lightbox();
3355
3356 $response_data = [];
3357
3358 // single provider?
3359 if ( $args['media_provider'] !== 'all' ) {
3360 // get provider
3361 $provider = $rl->providers[$args['media_provider']];
3362
3363 // add response data arguments if needed
3364 if ( ! empty( $provider['response_args'] ) ) {
3365 $response = $provider['instance']->get_response_data();
3366
3367 foreach ( $provider['response_args'] as $arg ) {
3368 if ( array_key_exists( $arg, $response ) )
3369 $response_data[$provider['slug']][$arg] = base64_encode( wp_json_encode( $response[$arg] ) );
3370 }
3371 }
3372 } else {
3373 // get active providers
3374 $providers = $rl->remote_library->get_active_providers();
3375
3376 if ( ! empty( $providers ) ) {
3377 foreach ( $providers as $provider ) {
3378 // get provider
3379 $provider = $rl->providers[$provider];
3380
3381 // add response data arguments if needed
3382 if ( ! empty( $provider['response_args'] ) ) {
3383 $response = $provider['instance']->get_response_data();
3384
3385 foreach ( $provider['response_args'] as $arg ) {
3386 if ( array_key_exists( $arg, $response ) )
3387 $response_data[$provider['slug']][$arg] = base64_encode( wp_json_encode( $response[$arg] ) );
3388 }
3389 }
3390 }
3391 }
3392 }
3393
3394 $data['response_data'] = $response_data;
3395 }
3396
3397 // parse excluded images
3398 $excluded = ! empty( $_POST['excluded'] ) && is_array( $_POST['excluded'] ) ? array_map( 'intval', $_POST['excluded'] ) : [];
3399
3400 // get excluded images
3401 if ( ! empty( $excluded ) )
3402 $excluded = array_unique( array_filter( $excluded ) );
3403
3404 // get media item template
3405 $media_item_template = $this->get_media_item_template( $this->fields['images'][$menu_item]['attachments']['preview'] );
3406
3407 // build html
3408 $html = '';
3409
3410 // any images?
3411 if ( ! empty( $images ) ) {
3412 foreach ( $images as $image ) {
3413 // get image content html
3414 $html .= $this->get_gallery_preview_image_content( $image, 'images', $menu_item, 'attachments', $media_item_template, $excluded, $image['id'] );
3415 }
3416 }
3417
3418 $data['images'] = $html;
3419
3420 if ( $this->fields['images'][$menu_item]['attachments']['preview']['pagination'] )
3421 $data['pagination'] = $this->get_preview_pagination( $args['preview_page'] );
3422
3423 // send JSON
3424 wp_send_json_success( $data );
3425 }
3426
3427 /**
3428 * Get gallery preview image content HTML.
3429 *
3430 * @param array $image
3431 * @param string $tab_id
3432 * @param string $menu_item
3433 * @param string $field_name
3434 * @param string $template
3435 * @param array $excluded
3436 * @param string|int $excluded_item
3437 * @return string
3438 */
3439 public function get_gallery_preview_image_content( $image, $tab_id, $menu_item, $field_name, $template, $excluded, $excluded_item = '' ) {
3440 // set flag
3441 if ( empty( $excluded_item ) )
3442 $excluded_flag = false;
3443 else
3444 $excluded_flag = in_array( $excluded_item, $excluded, true );
3445
3446 if ( $image['type'] === 'embed' ) {
3447 // replace all embed data
3448 $media_html = str_replace(
3449 [
3450 '__EMBED_ID__',
3451 '__EMBED_URL__',
3452 '__EMBED_WIDTH__',
3453 '__EMBED_HEIGHT__',
3454 '__EMBED_THUMBNAIL_URL__',
3455 '__EMBED_THUMBNAIL_WIDTH__',
3456 '__EMBED_THUMBNAIL_HEIGHT__',
3457 '__EMBED_TITLE__',
3458 '__EMBED_DESCRIPTION__',
3459 '__EMBED_DATE__'
3460 ],
3461 [
3462 esc_attr( $image['id'] ),
3463 esc_url( $image['url'] ),
3464 (int) $image['width'],
3465 (int) $image['height'],
3466 esc_url( $image['thumbnail_url'] ),
3467 (int) $image['thumbnail_width'],
3468 (int) $image['thumbnail_height'],
3469 esc_attr( $image['title'] ),
3470 esc_textarea( $image['caption'] ),
3471 esc_attr( $image['date'] )
3472 ],
3473 $this->get_media_embed_template( false )
3474 );
3475 } else
3476 $media_html = '';
3477
3478 // replace id and url of an image
3479 return str_replace(
3480 [
3481 '__MEDIA_DATA__',
3482 '__MEDIA_ID__',
3483 '__MEDIA_STATUS__',
3484 '__MEDIA_TYPE__'
3485 ],
3486 [
3487 $this->get_media_exclude_input_template( $tab_id, $menu_item, $field_name, $excluded_flag ? $excluded_item : '' ) . $media_html . $image['thumbnail_link'],
3488 esc_attr( $image['id'] ),
3489 $excluded_flag ? ' rl-status-inactive' : ' rl-status-active',
3490 esc_attr( $image['type'] )
3491 ],
3492 $template
3493 );
3494 }
3495
3496 /**
3497 * Get gallery image link.
3498 *
3499 * @param array $image Image data
3500 * @param mixed $size Image size
3501 * @param array $attr Image attributes
3502 * @return string
3503 */
3504 public function get_gallery_image_link( $image, $size = 'thumbnail', $attr = [] ) {
3505 $link = '';
3506
3507 if ( $size === 'thumbnail' ) {
3508 $url = $image['thumbnail_url'];
3509 $width = $image['thumbnail_width'];
3510 $height = $image['thumbnail_height'];
3511 } else {
3512 $url = $image['url'];
3513 $width = $image['width'];
3514 $height = $image['height'];
3515 }
3516
3517 if ( ! empty( $image['url'] ) ) {
3518 $size_class = $size;
3519
3520 if ( is_array( $size_class ) )
3521 $size_class = join( 'x', $size_class );
3522
3523 // combine attributes
3524 $attr = wp_parse_args(
3525 $attr,
3526 array(
3527 'src' => $url,
3528 'class' => 'attachment-' . $size_class . ' size-' . $size_class . ' format-' . ( $height > $width ? 'portrait' : 'landscape' ),
3529 'alt' => $image['alt']
3530 )
3531 );
3532
3533 // apply filters if any
3534 $attr = apply_filters( 'rl_get_gallery_image_attributes', $attr, $image, $size );
3535
3536 // start link output
3537 $link = rtrim( '<img ' . image_hwstring( $width, $height ) );
3538
3539 // add attributes
3540 foreach ( $attr as $name => $value ) {
3541 $link .= ' ' . esc_attr( $name ) . '="' . ( $name === 'src' ? esc_url( $value ) : esc_attr( $value ) ) . '"';
3542 }
3543
3544 // end link output
3545 $link .= ' />';
3546 }
3547
3548 return apply_filters( 'rl_get_gallery_image_link', $link, $image, $size );
3549 }
3550
3551 /**
3552 * Get attachment image source.
3553 *
3554 * @param int|string|array $image Attachment ID, image URL or array of image data
3555 * @param string $image_size Image size
3556 * @param string $thumbnail_size Thumbnail size
3557 * @return array
3558 */
3559 public function get_gallery_image_src( $image, $image_size = 'large', $thumbnail_size = 'thumbnail' ) {
3560 $imagedata = [];
3561
3562 // check difference in size between image and thumbnail
3563 $diff_sizes = $thumbnail_size !== $image_size;
3564
3565 // attachment id?
3566 if ( is_int( $image ) ) {
3567 if ( $image ) {
3568 $type = 'image';
3569 $width = 0;
3570 $height = 0;
3571
3572 // image src
3573 if ( wp_attachment_is_image( $image ) ) {
3574 $image_src = wp_get_attachment_image_src( $image, $image_size, false );
3575
3576 // different image and thumbnail sizes?
3577 if ( $diff_sizes )
3578 $thumbnail_src = wp_get_attachment_image_src( $image, $thumbnail_size, false );
3579 else
3580 $thumbnail_src = $image_src;
3581
3582 $file_url = $image_src[0];
3583 $width = $image_src[1];
3584 $height = $image_src[2];
3585 $thumbnail_url = $thumbnail_src[0];
3586 $thumbnail_width = $thumbnail_src[1];
3587 $thumbnail_height = $thumbnail_src[2];
3588 // video, blank thumbnail src
3589 } elseif ( rl_current_lightbox_supports( 'video' ) && wp_attachment_is( 'video', $image ) ) {
3590 $type = 'video';
3591 $thumbnail_id = $this->get_video_thumbnail_id( $image );
3592 $thumbnail_src = wp_get_attachment_image_src( $thumbnail_id, $image_size, false );
3593
3594 // get video metadata
3595 $meta = wp_get_attachment_metadata( $image );
3596
3597 if ( $meta ) {
3598 $width = $meta['width'];
3599 $height = $meta['height'];
3600 } else {
3601 $width = $thumbnail_src[1];
3602 $height = $thumbnail_src[2];
3603 }
3604
3605 // different image and thumbnail sizes?
3606 if ( $diff_sizes )
3607 $thumbnail_src = wp_get_attachment_image_src( $thumbnail_id, $thumbnail_size, false );
3608
3609 // file url
3610 $file_url = wp_get_attachment_url( $image );
3611 $thumbnail_url = $thumbnail_src[0];
3612 $thumbnail_width = $thumbnail_src[1];
3613 $thumbnail_height = $thumbnail_src[2];
3614 }
3615
3616 // get alternative text
3617 $alt = get_post_meta( $image, '_wp_attachment_image_alt', true );
3618
3619 // allow only strings
3620 if ( ! is_string( $alt ) )
3621 $alt = '';
3622
3623 $imagedata = array(
3624 'id' => $image,
3625 'title' => get_the_title( $image ),
3626 'date' => get_the_date( 'Y-m-d H:i:s', $image ),
3627 'caption' => '',
3628 'alt' => $alt,
3629 'url' => $file_url, // $image_src[0],
3630 'width' => $width,
3631 'height' => $height,
3632 'orientation' => $height > $width ? 'portrait' : 'landscape',
3633 'thumbnail_url' => $thumbnail_url,
3634 'thumbnail_width' => $thumbnail_width,
3635 'thumbnail_height' => $thumbnail_height,
3636 'type' => $type
3637 );
3638
3639 if ( $diff_sizes )
3640 $imagedata['thumbnail_orientation'] = $thumbnail_src[2] > $thumbnail_src[1] ? 'portrait' : 'landscape';
3641 else
3642 $imagedata['thumbnail_orientation'] = $imagedata['orientation'];
3643 }
3644 // image url
3645 } elseif ( is_string( $image ) ) {
3646 $imagedata['url'] = $image;
3647
3648 @list( $imagedata['width'], $imagedata['height'] ) = rl_get_image_size_by_url( $imagedata['url'] );
3649
3650 $imagedata = array(
3651 'id' => 0,
3652 'title' => '',
3653 'date' => '',
3654 'caption' => '',
3655 'alt' => '',
3656 'url' => $imagedata['url'],
3657 'width' => $imagedata['width'],
3658 'height' => $imagedata['height'],
3659 'orientation' => $imagedata['height'] > $imagedata['width'] ? 'portrait' : 'landscape',
3660 'thumbnail_url' => $imagedata['url'],
3661 'thumbnail_width' => $imagedata['width'],
3662 'thumbnail_height' => $imagedata['height'],
3663 'type' => 'image'
3664 );
3665
3666 $imagedata['thumbnail_orientation'] = $imagedata['orientation'];
3667 // full image array
3668 } elseif ( is_array( $image ) ) {
3669 // set width and height from url, if not available
3670 if ( empty( $image['width'] ) || empty( $image['height'] ) )
3671 @list( $image['width'], $image['height'] ) = rl_get_image_size_by_url( $image['url'] );
3672
3673 // set thumbnail data, if not available
3674 if ( empty( $image['thumbnail_url'] ) ) {
3675 $image['thumbnail_url'] = $image['url'];
3676 $image['thumbnail_width'] = $image['width'];
3677 $image['thumbnail_height'] = $image['height'];
3678 } else {
3679 // set thumbnail width and height from url, if not available
3680 if ( empty( $image['thumbnail_width'] ) || empty( $image['thumbnail_height'] ) )
3681 @list( $image['thumbnail_width'], $image['thumbnail_height'] ) = rl_get_image_size_by_url( $image['thumbnail_url'] );
3682 }
3683
3684 $imagedata = array(
3685 'id' => ! empty( $image['id'] ) ? ( preg_match( '/^e\d+$/', $image['id'] ) === 1 ? $image['id'] : (int) $image['id'] ) : 0,
3686 'title' => ! empty( $image['title'] ) ? ( $image['title'] ) : '',
3687 'date' => ! empty( $image['date'] ) ? ( $image['date'] ) : '',
3688 'caption' => ! empty( $image['caption'] ) ? ( $image['caption'] ) : '',
3689 'alt' => ! empty( $image['alt'] ) ? ( $image['alt'] ) : '',
3690 'url' => ! empty( $image['url'] ) ? esc_url_raw( $image['url'] ) : '',
3691 'width' => ! empty( $image['width'] ) ? (int) $image['width'] : 0,
3692 'height' => ! empty( $image['height'] ) ? (int) $image['height'] : 0,
3693 'thumbnail_url' => ! empty( $image['thumbnail_url'] ) ? esc_url_raw( $image['thumbnail_url'] ) : '',
3694 'thumbnail_width' => ! empty( $image['thumbnail_width'] ) ? (int) $image['thumbnail_width'] : 0,
3695 'thumbnail_height' => ! empty( $image['thumbnail_height'] ) ? (int) $image['thumbnail_height'] : 0,
3696 'link' => ! empty( $image['link'] ) ? esc_url_raw( $image['link'] ) : '',
3697 'thumbnail_link' => ! empty( $image['thumbnail_link'] ) ? esc_url_raw( $image['thumbnail_link'] ) : '',
3698 'type' => ! empty( $image['type'] ) ? ( $image['type'] ) : 'image'
3699 );
3700
3701 $imagedata['orientation'] = $imagedata['height'] > $imagedata['width'] ? 'portrait' : 'landscape';
3702 $imagedata['thumbnail_orientation'] = $imagedata['thumbnail_height'] > $imagedata['thumbnail_width'] ? 'portrait' : 'landscape';
3703 }
3704
3705 if ( ! empty( $imagedata ) ) {
3706 // link does not exist?
3707 if ( empty( $imagedata['link'] ) )
3708 $imagedata['link'] = $this->get_gallery_image_link( $imagedata, $image_size );
3709
3710 // thumbnail link does not exist?
3711 if ( empty( $imagedata['thumbnail_link'] ) ) {
3712 // different image and thumbnail sizes?
3713 if ( $diff_sizes )
3714 $imagedata['thumbnail_link'] = $this->get_gallery_image_link( $imagedata, $thumbnail_size );
3715 else
3716 $imagedata['thumbnail_link'] = $imagedata['link'];
3717 }
3718 }
3719
3720 return apply_filters( 'rl_get_gallery_image_src', $imagedata, $image, $image_size, $thumbnail_size );
3721 }
3722
3723 /**
3724 * Get gallery featured image.
3725 *
3726 * @param int $gallery_id
3727 * @param string $size Image size
3728 * @param array $attr Image attributes
3729 * @return string
3730 */
3731 public function get_featured_image( $gallery_id, $size = 'thumbnail', $attr = [] ) {
3732 $image = $this->get_featured_image_src( $gallery_id );
3733 $html = '';
3734
3735 if ( $image )
3736 $html = $this->get_gallery_image_link( $this->get_gallery_image_src( $image, 'large', $size ), $size, $attr );
3737
3738 return apply_filters( 'rl_get_featured_image', $html, $gallery_id, $size );
3739 }
3740
3741 /**
3742 * Get gallery featured image data.
3743 *
3744 * @param int $gallery_id
3745 * @return array
3746 */
3747 public function get_featured_image_src( $gallery_id ) {
3748 // get featured image data
3749 $featured_image_type = get_post_meta( $gallery_id, '_rl_featured_image_type', true );
3750 $featured_image = get_post_meta( $gallery_id, '_rl_featured_image', true );
3751
3752 switch ( $featured_image_type ) {
3753 // custom url
3754 case 'url':
3755 $frontend = function_exists( 'Responsive_Lightbox' ) ? Responsive_Lightbox()->frontend : null;
3756 if ( $frontend && method_exists( $frontend, 'sanitize_remote_image_url' ) )
3757 $featured_image = $frontend->sanitize_remote_image_url( $featured_image );
3758 else
3759 $featured_image = '';
3760
3761 if ( $featured_image !== '' ) {
3762 $image = esc_url( $featured_image );
3763 break;
3764 }
3765
3766 $image = $this->get_first_gallery_featured_image( $gallery_id );
3767 break;
3768
3769 // attachment id
3770 case 'id':
3771 $featured_image = (int) $featured_image;
3772 $image = wp_attachment_is_image( $featured_image ) ? $featured_image : $this->maybe_generate_thumbnail();
3773 break;
3774
3775 // first image
3776 case 'image':
3777 default:
3778 $image = $this->get_first_gallery_featured_image( $gallery_id );
3779 }
3780
3781 return apply_filters( 'rl_get_featured_image_src', $image, $gallery_id, $featured_image_type, $featured_image );
3782 }
3783
3784 /**
3785 * Helper to fetch the first gallery image data.
3786 *
3787 * @param int $gallery_id
3788 * @return array|int
3789 */
3790 protected function get_first_gallery_featured_image( $gallery_id ) {
3791 $images = $this->get_gallery_images(
3792 $gallery_id,
3793 [
3794 'exclude' => true,
3795 'limit' => 1
3796 ]
3797 );
3798
3799 if ( $images )
3800 return reset( $images );
3801
3802 return 0;
3803 }
3804
3805 /**
3806 * Get featured gallery attachments.
3807 *
3808 * @param array $args
3809 * @return array
3810 */
3811 public function gallery_query( $args ) {
3812 $attachments = [];
3813
3814 // get fields
3815 $fields = $this->fields['images']['featured'];
3816
3817 // force these settings
3818 $args['fields'] = 'ids';
3819 $args['tax_query'] = [];
3820 $args['meta_query'] = [];
3821 $args['author__in'] = [];
3822 $args['post_parent__in'] = [];
3823
3824 // get image source
3825 $args['image_source'] = isset( $args['image_source'] ) && array_key_exists( $args['image_source'], $fields['image_source']['options'] ) ? $args['image_source'] : $fields['image_source']['default'];
3826
3827 // get images per post
3828 $args['images_per_post'] = isset( $args['images_per_post'] ) ? absint( $args['images_per_post'] ) : $fields['images_per_post']['default'];
3829
3830 // get number of posts
3831 $args['number_of_posts'] = isset( $args['number_of_posts'] ) ? (int) $args['number_of_posts'] : $fields['number_of_posts']['default'];
3832
3833 // get all posts?
3834 if ( $args['number_of_posts'] <= 0 )
3835 $args['number_of_posts'] = -1;
3836
3837 // convert to wp query arg
3838 $args['posts_per_page'] = $args['number_of_posts'];
3839
3840 $args['order'] = isset( $args['order'] ) && array_key_exists( $args['order'], $fields['order']['options'] ) ? $args['order'] : $fields['order']['default'];
3841 $args['orderby'] = isset( $args['orderby'] ) && array_key_exists( $args['orderby'], $fields['orderby']['options'] ) ? $args['orderby'] : $fields['orderby']['default'];
3842 $args['offset'] = isset( $args['offset'] ) ? absint( $args['offset'] ) : 0;
3843
3844 $tax_queries = array(
3845 'post_format' => [],
3846 'post_term' => []
3847 );
3848
3849 $meta_queries = array(
3850 'page_template' => [],
3851 'image_source' => []
3852 );
3853
3854 // post type
3855 if ( ! empty( $args['post_type'] ) ) {
3856 // assign post types
3857 $post_types = $args['post_type'];
3858
3859 // clear post types
3860 $args['post_type'] = [];
3861
3862 foreach ( $post_types as $post_type ) {
3863 if ( array_key_exists( $post_type, $fields['post_type']['options'] ) )
3864 $args['post_type'][] = $post_type;
3865 }
3866 } else
3867 $args['post_type'] = $this->get_post_types( true );
3868
3869 // post status
3870 if ( ! empty( $args['post_status'] ) ) {
3871 // assign post statuses
3872 $post_statuses = $args['post_status'];
3873
3874 // clear post statuses
3875 $args['post_status'] = [];
3876
3877 foreach ( $post_statuses as $post_status ) {
3878 if ( array_key_exists( $post_status, $fields['post_status']['options'] ) )
3879 $args['post_status'][] = $post_status;
3880 }
3881 }
3882
3883 // post format
3884 if ( ! empty( $args['post_format'] ) ) {
3885 // assign post formats
3886 $post_formats = $args['post_format'];
3887
3888 foreach ( $post_formats as $post_format ) {
3889 if ( array_key_exists( $post_format, $fields['post_format']['options'] ) ) {
3890 // standard format?
3891 if ( $post_format === 'standard' ) {
3892 $tax_queries['post_format'][] = array(
3893 'relation' => 'OR',
3894 array(
3895 'taxonomy' => 'post_format',
3896 'field' => 'slug',
3897 'terms' => array( 'post-format-standard' )
3898 ),
3899 array(
3900 'taxonomy' => 'post_format',
3901 'field' => 'slug',
3902 'operator' => 'NOT EXISTS'
3903 )
3904 );
3905 } else {
3906 $tax_queries['post_format'][] = array(
3907 'taxonomy' => 'post_format',
3908 'field' => 'slug',
3909 'terms' => array( 'post-format-' . $post_format )
3910 );
3911 }
3912 }
3913 }
3914
3915 unset( $args['post_format'] );
3916 }
3917
3918 // page template
3919 if ( ! empty( $args['page_template'] ) ) {
3920 foreach ( $args['page_template'] as $page_template ) {
3921 if ( array_key_exists( $page_template, $fields['page_template']['options'] ) ) {
3922 if ( $page_template === 'default' ) {
3923 $meta_queries['page_template'][] = array(
3924 'relation' => 'OR',
3925 array(
3926 'key' => '_wp_page_template',
3927 'value' => 'default'
3928 ),
3929 array(
3930 'key' => '_wp_page_template',
3931 'value' => ''
3932 ),
3933 array(
3934 'key' => '_wp_page_template',
3935 'compare' => 'NOT EXISTS'
3936 )
3937 );
3938 } else {
3939 $meta_queries['page_template'][] = array(
3940 'key' => '_wp_page_template',
3941 'value' => $page_template
3942 );
3943 }
3944 }
3945 }
3946 }
3947
3948 // post author
3949 if ( ! empty( $args['post_author'] ) ) {
3950 foreach ( $args['post_author'] as $post_author ) {
3951 if ( array_key_exists( $post_author, $fields['post_author']['options'] ) )
3952 $args['author__in'][] = $post_author;
3953 }
3954 }
3955
3956 // page parent
3957 if ( ! empty( $args['page_parent'] ) ) {
3958 foreach ( $args['page_parent'] as $page_parent ) {
3959 if ( array_key_exists( $page_parent, $fields['page_parent']['options'] ) )
3960 $args['post_parent__in'][] = $page_parent;
3961 }
3962 }
3963
3964 // post term
3965 if ( ! empty( $args['post_term'] ) ) {
3966 $terms = [];
3967
3968 // get all terms
3969 if ( ! empty( $fields['post_term']['options'] ) ) {
3970 foreach ( $fields['post_term']['options'] as $tax => $data ) {
3971 $terms = array_merge( $terms, array_map( 'intval', array_keys( $data['terms'] ) ) );
3972 }
3973 }
3974
3975 foreach ( $args['post_term'] as $post_term ) {
3976 if ( in_array( $post_term, $terms ) ) {
3977 $term = get_term( $post_term );
3978
3979 $tax_queries['post_term'][] = array(
3980 'taxonomy' => $term->taxonomy,
3981 'field' => 'term_id',
3982 'terms' => (int) $post_term
3983 );
3984 }
3985 }
3986 }
3987
3988 switch ( $args['image_source'] ) {
3989 case 'thumbnails':
3990 $meta_queries['image_source'][] = array(
3991 'relation' => 'OR',
3992 array(
3993 'key' => '_thumbnail_id',
3994 'compare' => 'EXISTS'
3995 )
3996 );
3997 }
3998
3999 // any tax queries?
4000 if ( ! empty( $tax_queries['post_term'] ) || ! empty( $tax_queries['post_format'] ) ) {
4001 $args['tax_query'] = array( 'relation' => 'AND' );
4002
4003 if ( ! empty( $tax_queries['post_term'] ) )
4004 $args['tax_query'][] = array( 'relation' => 'OR' ) + $tax_queries['post_term'];
4005
4006 if ( ! empty( $tax_queries['post_format'] ) )
4007 $args['tax_query'][] = array( 'relation' => 'OR' ) + $tax_queries['post_format'];
4008 }
4009
4010 // any tax queries?
4011 if ( ! empty( $meta_queries['page_template'] ) || ! empty( $meta_queries['image_source'] ) ) {
4012 $args['meta_query'] = array( 'relation' => 'AND' );
4013
4014 if ( ! empty( $meta_queries['page_template'] ) )
4015 $args['meta_query'][] = array( 'relation' => 'OR', $meta_queries['page_template'] );
4016
4017 if ( ! empty( $meta_queries['image_source'] ) )
4018 $args['meta_query'][] = array( 'relation' => 'OR', $meta_queries['image_source'] );
4019 }
4020
4021 // get posts
4022 $query = new WP_Query( apply_filters( 'rl_gallery_query_args', $args ) );
4023
4024 // get attachments
4025 if ( $query->have_posts() )
4026 $attachments = $this->get_gallery_query_attachments( $query->posts, $args );
4027
4028 return $attachments;
4029 }
4030
4031 /**
4032 * Get query attachments.
4033 *
4034 * @param array $posts Post IDs, array or objects
4035 * @param array $args Additional arguments
4036 * @return array
4037 */
4038 public function get_gallery_query_attachments( $posts, $args ) {
4039 $attachments = [];
4040
4041 // any posts?
4042 if ( ! empty( $posts ) ) {
4043 switch ( $args['image_source'] ) {
4044 case 'thumbnails':
4045 $nop = count( $posts ) - 1;
4046
4047 foreach ( $posts as $number => $post_id ) {
4048 $attachment_id = (int) get_post_thumbnail_id( $post_id );
4049
4050 // real attachment?
4051 if ( wp_attachment_is_image( $attachment_id ) )
4052 $attachments[] = $attachment_id;
4053 else
4054 continue;
4055
4056 if ( $args['preview'] ) {
4057 $attachments = array_unique( $attachments );
4058 $noa = count( $attachments );
4059
4060 if ( ( $noa >= ( $args['preview_per_page'] * $args['preview_page'] ) ) || $nop === $number ) {
4061 $attachments = array_slice( $attachments, ( $args['preview_page'] - 1 ) * $args['preview_per_page'], $args['preview_per_page'], false );
4062
4063 break;
4064 }
4065 }
4066 }
4067 break;
4068
4069 case 'attached_images':
4070 $nop = count( $posts ) - 1;
4071
4072 foreach ( $posts as $number => $post_id ) {
4073 // get attached images, do not use get_attached_media here!
4074 $attachment_ids = (array) get_children(
4075 array(
4076 'post_parent' => $post_id,
4077 'post_status' => 'inherit',
4078 'post_type' => 'attachment',
4079 'post_mime_type' => 'image',
4080 'posts_per_page' => $args['images_per_post'],
4081 'order' => 'ASC',
4082 'orderby' => 'menu_order',
4083 'nopaging' => false,
4084 'page' => 1,
4085 'fields' => 'ids'
4086 )
4087 );
4088
4089 if ( $attachment_ids ) {
4090 foreach ( $attachment_ids as $attachment_id ) {
4091 if ( ! empty( $attachment_id ) ) {
4092 $attachments[] = $attachment_id;
4093 }
4094 }
4095 }
4096
4097 if ( $args['preview'] ) {
4098 $attachments = array_unique( $attachments );
4099 $noa = count( $attachments );
4100
4101 if ( ( $noa >= ( $args['preview_per_page'] * $args['preview_page'] ) ) || $nop === $number ) {
4102 $attachments = array_slice( $attachments, ( $args['preview_page'] - 1 ) * $args['preview_per_page'], $args['preview_per_page'], false );
4103
4104 break;
4105 }
4106 }
4107 }
4108 }
4109 }
4110
4111 return apply_filters( 'rl_get_gallery_query_attachments', array_unique( $attachments ), $posts, $args );
4112 }
4113
4114 /**
4115 * Load featured content query args.
4116 *
4117 * @global string $pagenow
4118 *
4119 * @return void
4120 */
4121 public function init_admin() {
4122 global $pagenow;
4123
4124 // check values
4125 $post = isset( $_GET['post'] ) ? (int) $_GET['post'] : 0;
4126 $post_id = isset( $_POST['post_ID'] ) ? (int) $_POST['post_ID'] : 0;
4127 $action = isset( $_POST['action'] ) ? sanitize_key( $_POST['action'] ) : '';
4128 $post_type = isset( $_POST['post_type'] ) ? sanitize_key( $_POST['post_type'] ) : '';
4129
4130 // prepare query arguments if needed
4131 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 ) ) )
4132 $this->fields['images']['featured'] = $this->prepare_featured_fields( $this->fields['images']['featured'] );
4133
4134 // add default thumbnail image if needed
4135 if ( Responsive_Lightbox()->options['builder']['gallery_builder'] && $pagenow === 'edit.php' && $post_type && $post_type === 'rl_gallery' )
4136 $this->maybe_generate_thumbnail();
4137 }
4138
4139 /**
4140 * Generate post thumbnail replacement.
4141 *
4142 * @return int
4143 */
4144 public function maybe_generate_thumbnail() {
4145 // get old attachment
4146 $thumbnail_id = get_posts(
4147 array(
4148 'name' => 'responsive-lightbox-thumbnail',
4149 'post_type' => 'attachment',
4150 'post_status' => 'inherit',
4151 'numberposts' => 1,
4152 'fields' => 'ids'
4153 )
4154 );
4155
4156 // no attachment?
4157 if ( empty( $thumbnail_id ) ) {
4158 // get new attachment
4159 $thumbnail_id = get_posts(
4160 array(
4161 'name' => 'responsive-lightbox-thumbnail',
4162 'post_type' => 'attachment',
4163 'post_status' => 'pending',
4164 'numberposts' => 1,
4165 'fields' => 'ids'
4166 )
4167 );
4168
4169 // no attachment?
4170 if ( empty( $thumbnail_id ) ) {
4171 // get upload directory data
4172 $wp_upload_dir = wp_upload_dir();
4173
4174 // get file path
4175 $filepath = str_replace( '\\', '/', RESPONSIVE_LIGHTBOX_PATH . 'images/responsive-lightbox-thumbnail.png' );
4176
4177 // get file name
4178 $filename = basename( $filepath );
4179
4180 // new filepath in upload dir
4181 $new_filepath = $wp_upload_dir['path'] . '/' . $filename;
4182
4183 // copty file to upload dir
4184 copy( $filepath, $new_filepath );
4185
4186 // get type of file
4187 $filetype = wp_check_filetype( $filename );
4188
4189 // force pending status for the attachment
4190 add_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
4191
4192 // insert attachment
4193 $thumbnail_id = wp_insert_attachment(
4194 array(
4195 'guid' => $wp_upload_dir['url'] . '/' . $filename,
4196 'post_mime_type' => $filetype['type'],
4197 'post_title' => preg_replace( '/\.[^.]+$/', '', $filename ),
4198 'post_content' => '',
4199 'post_parent' => 0,
4200 'post_status' => 'inherit'
4201 ),
4202 $new_filepath,
4203 0
4204 );
4205
4206 remove_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
4207
4208 // success?
4209 if ( $thumbnail_id ) {
4210 // make sure that this file is included
4211 require_once( ABSPATH . 'wp-admin/includes/image.php' );
4212
4213 // update database with generated metadata for the attachment
4214 wp_update_attachment_metadata( $thumbnail_id, wp_generate_attachment_metadata( $thumbnail_id, $new_filepath ) );
4215 }
4216 } else
4217 $thumbnail_id = $thumbnail_id[0];
4218 } else {
4219 // force pending status for the attachment
4220 add_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
4221
4222 $thumbnail_id = wp_update_post(
4223 array(
4224 'ID' => $thumbnail_id[0],
4225 'post_status' => 'pending'
4226 )
4227 );
4228
4229 remove_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
4230 }
4231
4232 return (int) $thumbnail_id;
4233 }
4234
4235 /**
4236 * Get video thumbnail replacement.
4237 *
4238 * @param int $post_id
4239 * @return int
4240 */
4241 public function get_video_thumbnail_id( $post_id ) {
4242 $thumbnail_id = 0;
4243
4244 // try to get video thumbnail
4245 $attachment_id = (int) get_post_thumbnail_id( $post_id );
4246
4247 // real attachment?
4248 if ( wp_attachment_is_image( $attachment_id ) )
4249 $thumbnail_id = $attachment_id;
4250
4251 // try to get default video poster image
4252 if ( ! $thumbnail_id ) {
4253 $thumbnail_id = get_posts(
4254 array(
4255 'name' => 'responsive-lightbox-video-thumbnail',
4256 'post_type' => 'attachment',
4257 'post_status' => 'inherit',
4258 'numberposts' => 1,
4259 'fields' => 'ids'
4260 )
4261 );
4262 }
4263
4264 // no attachment?
4265 if ( ! $thumbnail_id ) {
4266 // get new attachment
4267 $thumbnail_id = get_posts(
4268 array(
4269 'name' => 'responsive-lightbox-video-thumbnail',
4270 'post_type' => 'attachment',
4271 'post_status' => 'pending',
4272 'numberposts' => 1,
4273 'fields' => 'ids'
4274 )
4275 );
4276
4277 // no attachment?
4278 if ( ! $thumbnail_id ) {
4279 // get upload directory data
4280 $wp_upload_dir = wp_upload_dir();
4281
4282 // get file path
4283 $filepath = str_replace( '\\', '/', RESPONSIVE_LIGHTBOX_PATH . 'images/responsive-lightbox-video-thumbnail.png' );
4284
4285 // get file name
4286 $filename = basename( $filepath );
4287
4288 // new filepath in upload dir
4289 $new_filepath = $wp_upload_dir['path'] . '/' . $filename;
4290
4291 // copty file to upload dir
4292 copy( $filepath, $new_filepath );
4293
4294 // get type of file
4295 $filetype = wp_check_filetype( $filename );
4296
4297 // force pending status for the attachment
4298 add_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
4299
4300 // insert attachment
4301 $thumbnail_id = wp_insert_attachment(
4302 array(
4303 'guid' => $wp_upload_dir['url'] . '/' . $filename,
4304 'post_mime_type' => $filetype['type'],
4305 'post_title' => preg_replace( '/\.[^.]+$/', '', $filename ),
4306 'post_content' => '',
4307 'post_parent' => 0,
4308 'post_status' => 'inherit'
4309 ),
4310 $new_filepath,
4311 0
4312 );
4313
4314 remove_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
4315
4316 // success?
4317 if ( $thumbnail_id ) {
4318 // make sure that this file is included
4319 require_once( ABSPATH . 'wp-admin/includes/image.php' );
4320
4321 // update database with generated metadata for the attachment
4322 wp_update_attachment_metadata( $thumbnail_id, wp_generate_attachment_metadata( $thumbnail_id, $new_filepath ) );
4323 }
4324 } else
4325 $thumbnail_id = $thumbnail_id[0];
4326 }
4327
4328 return (int) $thumbnail_id;
4329 }
4330
4331 /**
4332 * Change status of new attachment thumbnail replacement.
4333 *
4334 * @param array $data
4335 * @return array
4336 */
4337 function set_attachment_post_status( $data ) {
4338 $data['post_status'] = 'pending';
4339
4340 return $data;
4341 }
4342
4343 /**
4344 * Prepare featured content fields.
4345 *
4346 * @param array $fields
4347 * @return array
4348 */
4349 public function prepare_featured_fields( $fields ) {
4350 foreach ( array( 'post_type', 'post_status', 'post_format', 'post_term', 'post_author', 'page_parent', 'page_template' ) as $option ) {
4351 $fields[$option]['options'] = $this->prepare_query_args( $option );
4352 }
4353
4354 return $fields;
4355 }
4356
4357 /**
4358 * Prepare values option list.
4359 *
4360 * @param string $type
4361 * @return array
4362 */
4363 public function prepare_query_args( $type = '' ) {
4364 $html = '';
4365
4366 switch( $type ) {
4367 case 'post_type':
4368 $data = $this->get_post_types();
4369 break;
4370
4371 case 'post_status':
4372 $data = $this->get_post_statuses();
4373 break;
4374
4375 case 'post_format':
4376 $data = $this->get_post_formats();
4377 break;
4378
4379 case 'post_term':
4380 $taxonomies = $this->get_taxonomies();
4381 $new_terms = [];
4382
4383 if ( ! empty( $taxonomies ) ) {
4384 foreach ( $taxonomies as $tax_id => $label ) {
4385 $terms = get_terms(
4386 array(
4387 'taxonomy' => $tax_id,
4388 'orderby' => 'name',
4389 'order' => 'ASC',
4390 'hide_empty' => false,
4391 'fields' => 'id=>name'
4392 )
4393 );
4394
4395 if ( ! empty( $terms ) )
4396 $new_terms[$tax_id] = array(
4397 'label' => $label,
4398 'terms' => $terms
4399 );
4400 }
4401 }
4402
4403 $data = $new_terms;
4404 break;
4405
4406 case 'post_author':
4407 $data = $this->get_users();
4408 break;
4409
4410 case 'page_parent':
4411 $parents = [];
4412 $hierarchical = get_post_types(
4413 array(
4414 'public' => true,
4415 'hierarchical' => true
4416 ),
4417 'objects',
4418 'and'
4419 );
4420
4421 if ( ! empty( $hierarchical ) ) {
4422 foreach ( $hierarchical as $post_type => $object ) {
4423 // get top level hierarchical posts
4424 $query = new WP_Query(
4425 array(
4426 'post_type' => $post_type,
4427 'post_status' => 'publish',
4428 'nopaging' => true,
4429 'posts_per_page' => -1,
4430 'orderby' => 'title',
4431 'order' => 'ASC',
4432 'suppress_filters' => false,
4433 'no_found_rows' => true,
4434 'cache_results' => false,
4435 'post_parent' => 0
4436 )
4437 );
4438
4439 if ( ! empty( $query->posts ) ) {
4440 foreach ( $query->posts as $post ) {
4441 $parents[$post->ID] = trim( $post->post_title ) === '' ? __( 'Untitled' ) : $post->post_title;
4442 }
4443 }
4444 }
4445 }
4446
4447 $data = $parents;
4448 break;
4449
4450 case 'page_template':
4451 $data = $this->get_page_templates();
4452 break;
4453
4454 default:
4455 $data = [];
4456 }
4457
4458 return apply_filters( 'rl_galleries_prepare_query_args', $data, $type );
4459 }
4460
4461 /**
4462 * Get public post types.
4463 *
4464 * @param bool $simple Which data should be returned
4465 * @param bool $skip Which post types should be skipped
4466 * @return array
4467 */
4468 public function get_post_types( $simple = false, $skip = [ 'attachment', 'rl_gallery' ] ) {
4469 $post_types = get_post_types(
4470 array(
4471 'public' => true
4472 ),
4473 'objects',
4474 'and'
4475 );
4476
4477 $data = [];
4478
4479 if ( ! empty( $post_types ) ) {
4480 foreach ( $post_types as $post_type => $cpt ) {
4481 // skip unwanted post types
4482 if ( in_array( $post_type, $skip, true ) )
4483 continue;
4484
4485 if ( $simple )
4486 $data[] = $post_type;
4487 else
4488 $data[$post_type] = $cpt->labels->singular_name;
4489 }
4490 }
4491
4492 if ( ! $simple )
4493 asort( $data );
4494
4495 return $data;
4496 }
4497
4498 /**
4499 * Get post statuses.
4500 *
4501 * @return array
4502 */
4503 public function get_post_statuses() {
4504 $post_statuses = get_post_stati();
4505
4506 asort( $post_statuses );
4507
4508 // remove inherit post status
4509 if ( isset( $post_statuses['inherit'] ) )
4510 unset( $post_statuses['inherit'] );
4511
4512 return $post_statuses;
4513 }
4514
4515 /**
4516 * Get post formats.
4517 *
4518 * @return array
4519 */
4520 public function get_post_formats() {
4521 $post_formats = array(
4522 'aside' => __( 'Aside' ),
4523 'audio' => __( 'Audio' ),
4524 'chat' => __( 'Chat' ),
4525 'gallery' => __( 'Gallery' ),
4526 'link' => __( 'Link' ),
4527 'photo' => __( 'Photo' ),
4528 'quote' => __( 'Quote' ),
4529 'standard' => __( 'Standard' ),
4530 'status' => __( 'Status' ),
4531 'video' => __( 'Video' )
4532 );
4533
4534 asort( $post_formats );
4535
4536 return $post_formats;
4537 }
4538
4539 /**
4540 * Get taxonomies.
4541 *
4542 * @return array
4543 */
4544 public function get_taxonomies() {
4545 $taxonomies = get_taxonomies(
4546 array(
4547 'public' => true
4548 ),
4549 'objects',
4550 'and'
4551 );
4552
4553 // remove post format
4554 if ( array_key_exists( 'post_format', $taxonomies ) )
4555 unset( $taxonomies['post_format'] );
4556
4557 // get main instance
4558 $rl = Responsive_Lightbox();
4559
4560 // remove gallery categories
4561 if ( $rl->options['builder']['categories'] && array_key_exists( 'rl_category', $taxonomies ) )
4562 unset( $taxonomies['rl_category'] );
4563
4564 // remove gallery tags
4565 if ( $rl->options['builder']['tags'] && array_key_exists( 'rl_tag', $taxonomies ) )
4566 unset( $taxonomies['rl_tag'] );
4567
4568 if ( $rl->options['folders']['active'] ) {
4569 // remove media folders categories
4570 unset( $taxonomies['rl_media_folder'] );
4571
4572 // remove custom media folders categories
4573 if ( $rl->options['folders']['media_taxonomy'] !== 'rl_media_folder' )
4574 unset( $taxonomies[$rl->options['folders']['media_taxonomy']] );
4575
4576 // remove media folders tags
4577 if ( $rl->options['folders']['media_tags'] )
4578 unset( $taxonomies['rl_media_tag'] );
4579 }
4580
4581 $data = [];
4582
4583 if ( ! empty( $taxonomies ) ) {
4584 foreach ( $taxonomies as $tax_id => $taxonomy ) {
4585 $data[$tax_id] = $taxonomy->labels->singular_name;
4586 }
4587 }
4588
4589 // sort taxonomies
4590 asort( $data );
4591
4592 return $data;
4593 }
4594
4595 /**
4596 * Get users.
4597 *
4598 * @return array
4599 */
4600 public function get_users() {
4601 $users = get_users(
4602 array(
4603 'fields' => array( 'ID', 'user_login' )
4604 )
4605 );
4606
4607 $data = [];
4608
4609 if ( ! empty( $users ) ) {
4610 foreach ( $users as $user ) {
4611 $data[(int) $user->ID] = $user->user_login;
4612 }
4613 }
4614
4615 asort( $data );
4616
4617 return $data;
4618 }
4619
4620 /**
4621 * Get page templates.
4622 *
4623 * @return array
4624 */
4625 public function get_page_templates() {
4626 $data = [];
4627 $page_templates = wp_get_theme()->get_page_templates();
4628
4629 if ( ! empty( $page_templates ) )
4630 asort( $page_templates );
4631
4632 $data = array_merge( array( 'default' => apply_filters( 'default_page_template_title', __( 'Default Template' ) ) ), $page_templates );
4633
4634 return $data;
4635 }
4636
4637 /**
4638 * Fix possible misplaced or hidden metaboxes do to old 'after_title' metabox and possibility to move internal metaboxes.
4639 *
4640 * @return void
4641 */
4642 public function clear_metaboxes( $screen ) {
4643 global $pagenow;
4644
4645 if ( ! ( ( $pagenow === 'post.php' || $pagenow === 'post-new.php' ) && ! empty( $screen->post_type ) && $screen->post_type === 'rl_gallery' && empty( $_POST['rl_gallery'] ) ) )
4646 return;
4647
4648 // get user id
4649 $user_id = get_current_user_id();
4650
4651 // get rl metaboxes
4652 $order = get_user_meta( $user_id, 'meta-box-order_rl_gallery', true );
4653
4654 // any metabox order? fix possible misplaced metaboxes
4655 if ( is_array( $order ) && ! empty( $order ) ) {
4656 // save metaboxes
4657 $_order = $order;
4658
4659 // default rl metaboxes
4660 $rl_boxes = [ 'responsive-gallery-images', 'responsive-gallery-config', 'responsive-gallery-design', 'responsive-gallery-paging', 'responsive-gallery-lightbox', 'responsive-gallery-misc' ];
4661
4662 foreach ( $_order as $group => $metaboxes ) {
4663 if ( $group === 'after_title' ) {
4664 // remove deprecated after_title metabox
4665 unset( $order['after_title'] );
4666 } elseif ( $metaboxes !== '' ) {
4667 $boxes = explode( ',', $metaboxes );
4668 $new_boxes = [];
4669
4670 foreach ( $boxes as $box ) {
4671 if ( ! in_array( $box, $rl_boxes, true ) )
4672 $new_boxes[] = $box;
4673 }
4674
4675 if ( ! empty( $new_boxes ) )
4676 $order[$group] = implode( ',', $new_boxes );
4677 else
4678 $order[$group] = '';
4679 }
4680 }
4681
4682 // remove default metaboxes storage
4683 if ( array_key_exists( 'responsive_lightbox_metaboxes', $order ) )
4684 unset( $order['responsive_lightbox_metaboxes'] );
4685
4686 // update usermeta to prevent issues with rl metaboxes
4687 if ( $order !== $_order )
4688 update_user_meta( $user_id, 'meta-box-order_rl_gallery', $order );
4689 }
4690 }
4691
4692 /**
4693 * Save gallery metadata.
4694 *
4695 * @param int $post_id
4696 * @param object $post
4697 * @param bool $update Whether existing post is being updated or not
4698 * @return void
4699 */
4700 public function save_post( $post_id, $post, $update ) {
4701 // check action
4702 $action = isset( $_GET['action'] ) ? sanitize_key( $_GET['action'] ) : '';
4703
4704 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'] ) )
4705 return;
4706
4707 // save gallery
4708 $this->save_gallery( wp_unslash( $_POST ), $post_id );
4709 }
4710
4711 /**
4712 * Save gallery preview metadata.
4713 *
4714 * @param array $post_data Gallery data
4715 * @param int $post_id
4716 * @param bool $preview Whether is it preview
4717 * @return void
4718 */
4719 public function save_gallery( $post_data, $post_id, $preview = false ) {
4720 // get gallery data
4721 $data = $post_data['rl_gallery'];
4722
4723 // prepare sanitized data
4724 $safedata = [];
4725
4726 // sanitize all fields
4727 foreach ( $this->fields as $tab_id => $menu_items ) {
4728 switch ( $tab_id ) {
4729 case 'config':
4730 // get main instance
4731 $rl = Responsive_Lightbox();
4732
4733 // add menu item
4734 $menu_item = isset( $data[$tab_id], $data[$tab_id]['menu_item'] ) && array_key_exists( $data[$tab_id]['menu_item'], $this->tabs[$tab_id]['menu_items'] ) ? $data[$tab_id]['menu_item'] : reset( $this->tabs[$tab_id]['menu_items'] );
4735
4736 // get default gallery fields
4737 $default_gallery_fields = $rl->frontend->get_default_gallery_fields();
4738
4739 // prepare fields
4740 if ( $menu_item === 'default' )
4741 $items = $default_gallery_fields;
4742 else {
4743 // assign settings and defaults
4744 $fields = $rl->settings->settings[$menu_item . '_gallery']['fields'];
4745 $defaults = $rl->defaults[$menu_item . '_gallery'];
4746
4747 // make a copy
4748 $fields_copy = $fields;
4749
4750 foreach ( $fields_copy as $field_id => $field ) {
4751 if ( $field['type'] === 'multiple' ) {
4752 foreach ( $field['fields'] as $subfield_id => $subfield ) {
4753 $fields[$field_id]['fields'][$subfield_id]['default'] = $defaults[$subfield_id];
4754 }
4755 } else
4756 $fields[$field_id]['default'] = $defaults[$field_id];
4757 }
4758
4759 $items = $rl->frontend->get_unique_fields( $default_gallery_fields, $fields );
4760 }
4761
4762 // sanitize fields
4763 $safedata = $this->sanitize_fields( $items, $data, $tab_id, $menu_item );
4764
4765 // add menu item
4766 $safedata[$tab_id]['menu_item'] = $menu_item;
4767 break;
4768
4769 default:
4770 // add menu item
4771 $menu_item = isset( $data[$tab_id], $data[$tab_id]['menu_item'] ) && array_key_exists( $data[$tab_id]['menu_item'], $this->tabs[$tab_id]['menu_items'] ) ? $data[$tab_id]['menu_item'] : 'options';
4772
4773 // sanitize fields
4774 $safedata = $this->sanitize_fields( $menu_items[$menu_item], $data, $tab_id, $menu_item );
4775
4776 // add menu item
4777 $safedata[$tab_id]['menu_item'] = $menu_item;
4778 }
4779
4780 $safedata[$tab_id] = apply_filters( 'rl_gallery_tab_metadata', $safedata[$tab_id], $tab_id );
4781
4782 // preview?
4783 if ( $preview )
4784 update_metadata( 'post', $post_id, '_rl_' . $tab_id, $safedata[$tab_id] );
4785 else
4786 update_post_meta( $post_id, '_rl_' . $tab_id, $safedata[$tab_id] );
4787 }
4788
4789 $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';
4790
4791 switch ( $featured_image_type ) {
4792 // custom url
4793 case 'url':
4794 $thumbnail_id = $this->maybe_generate_thumbnail();
4795 $frontend = function_exists( 'Responsive_Lightbox' ) ? Responsive_Lightbox()->frontend : null;
4796 $custom_url = isset( $post_data['_rl_thumbnail_url'] ) ? $post_data['_rl_thumbnail_url'] : '';
4797 if ( $frontend && method_exists( $frontend, 'sanitize_remote_image_url' ) )
4798 $featured_image = $frontend->sanitize_remote_image_url( $custom_url );
4799 else
4800 $featured_image = '';
4801
4802 if ( $featured_image === '' )
4803 $featured_image_type = 'image';
4804 break;
4805
4806 // first image
4807 case 'image':
4808 $thumbnail_id = $this->maybe_generate_thumbnail();
4809 $featured_image = '';
4810 break;
4811
4812 // attachment id
4813 case 'id':
4814 default:
4815 $featured_image = $thumbnail_id = isset( $post_data['_thumbnail_id'] ) ? (int) $post_data['_thumbnail_id'] : 0;
4816 }
4817
4818 // preview?
4819 if ( $preview ) {
4820 update_metadata( 'post', $post_id, '_rl_featured_image_type', $featured_image_type );
4821 update_metadata( 'post', $post_id, '_rl_featured_image', $featured_image );
4822 update_metadata( 'post', $post_id, '_thumbnail_id', $thumbnail_id );
4823 } else {
4824 // update featured image
4825 update_post_meta( $post_id, '_rl_featured_image_type', $featured_image_type );
4826 update_post_meta( $post_id, '_rl_featured_image', $featured_image );
4827 update_post_meta( $post_id, '_thumbnail_id', $thumbnail_id );
4828
4829 // save number of images
4830 update_post_meta( $post_id, '_rl_images_count', $this->get_gallery_images_number( $post_id ) );
4831 }
4832
4833 // update post excerpt
4834 if ( isset( $safedata['misc']['options']['gallery_description'] ) ) {
4835 remove_action( 'save_post_rl_gallery', [ $this, 'save_post' ], 10, 3 );
4836
4837 $postdata = [
4838 'ID' => $post_id,
4839 'post_excerpt' => sanitize_textarea_field( $safedata['misc']['options']['gallery_description'] )
4840 ];
4841
4842 wp_update_post( $postdata );
4843
4844 add_action( 'save_post_rl_gallery', [ $this, 'save_post' ], 10, 3 );
4845 }
4846 }
4847
4848 /**
4849 * Check attachments IDs.
4850 *
4851 * @param array $attachments Attachment ID's
4852 * @param array $args
4853 * @return array
4854 */
4855 public function check_attachments( $attachments, $args = [] ) {
4856 // no attachments?
4857 if ( empty( $attachments ) || ! is_array( $attachments ) )
4858 return [];
4859
4860 // check providers support
4861 if ( ! empty( $args['providers'] ) )
4862 $embed = rl_current_lightbox_supports( $args['providers'], 'OR' );
4863 else
4864 $embed = false;
4865
4866 // no embed data?
4867 if ( ! $embed )
4868 $copy = array_map( 'intval', $attachments );
4869 else
4870 $copy = $attachments;
4871
4872 // check attachments
4873 foreach ( $attachments as $key => $attachment_id ) {
4874 // embed?
4875 if ( $embed && preg_match( '/^e\d+$/', $attachment_id ) === 1 ) {
4876 if ( ! in_array( $attachment_id, $args['embed_keys'], true ) )
4877 unset( $copy[$key] );
4878 // video support?
4879 } elseif ( rl_current_lightbox_supports( 'video' ) ) {
4880 // is it an image or video?
4881 if ( ! wp_attachment_is( 'video', $attachment_id ) && ! wp_attachment_is( 'image', $attachment_id ) )
4882 unset( $copy[$key] );
4883 // make sure it's integer
4884 elseif ( $embed )
4885 $copy[$key] = (int) $copy[$key];
4886 } else {
4887 // is it an image?
4888 if ( ! wp_attachment_is_image( $attachment_id ) )
4889 unset( $copy[$key] );
4890 // make sure it's integer
4891 elseif ( $embed )
4892 $copy[$key] = (int) $copy[$key];
4893 }
4894 }
4895
4896 return array_values( $copy );
4897 }
4898
4899 /**
4900 * Display shortcode metabox.
4901 *
4902 * @param object $post
4903 * @return void
4904 */
4905 public function shortcode_metabox( $post ) {
4906 echo '
4907 <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>
4908 <code class="rl-shortcode" data-number="0">[rl_gallery id=&quot;' . (int) $post->ID . '&quot;]</code>
4909 <p>' . esc_html__( 'You can also place this gallery into your template files by using the template tag below', 'responsive-lightbox' ) . ':</p>
4910 <code class="rl-shortcode" data-number="1">if ( function_exists( \'rl_gallery\' ) ) { rl_gallery( \'' . (int) $post->ID . '\' ); }</code>';
4911 }
4912
4913 /**
4914 * Add new gallery listing columns.
4915 *
4916 * @param array $columns
4917 * @return array
4918 */
4919 public function gallery_columns( $columns ) {
4920 // find title position
4921 $offset = array_search( 'title', array_keys( $columns ) );
4922
4923 // put image column before title
4924 $columns = array_merge(
4925 array_slice( $columns, 0, $offset ),
4926 array(
4927 'image' => esc_html__( 'Gallery', 'responsive-lightbox' )
4928 ),
4929 array_slice( $columns, $offset )
4930 );
4931
4932 // put new columns after title
4933 $columns = array_merge(
4934 array_slice( $columns, 0, $offset + 2 ),
4935 array(
4936 'shortcode' => esc_html__( 'Shortcode', 'responsive-lightbox' ),
4937 'type' => esc_html__( 'Type', 'responsive-lightbox' ),
4938 'source' => esc_html__( 'Source', 'responsive-lightbox' )
4939 ),
4940 array_slice( $columns, $offset + 2 )
4941 );
4942
4943 return $columns;
4944 }
4945
4946 /**
4947 * Add new gallery listing columns content.
4948 *
4949 * @global string $pagenow
4950 *
4951 * @param string $column_name
4952 * @param int $post_id
4953 * @return void
4954 */
4955 public function gallery_columns_content( $column_name, $post_id ) {
4956 global $pagenow;
4957
4958 if ( $pagenow === 'edit.php' ) {
4959 switch ( $column_name ) {
4960 case 'image':
4961 // get image data, based on gallery source type
4962 $image = $this->get_featured_image( $post_id, 'thumbnail' );
4963 $images_count = (int) get_post_meta( $post_id, '_rl_images_count', true );
4964
4965 // display count
4966 if ( ! empty( $image ) )
4967 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>';
4968 else
4969 echo '<span class="media-icon image-icon">' . wp_get_attachment_image( 0, array( 60, 60 ), true, array( 'alt' => '' ) ) . '</span>';
4970 break;
4971
4972 case 'shortcode':
4973 echo '<code>[rl_gallery id="' . (int) $post_id . '"]</code>';
4974 break;
4975
4976 case 'type':
4977 $config = get_post_meta( $post_id, '_rl_config', true );
4978
4979 if ( ! empty( $config['menu_item'] ) && array_key_exists( $config['menu_item'], $this->tabs['config']['menu_items'] ) ) {
4980 echo esc_html( $this->tabs['config']['menu_items'][$config['menu_item']] );
4981
4982 if ( $config['menu_item'] === 'default' )
4983 echo esc_html( ' (' . $this->tabs['config']['menu_items'][Responsive_Lightbox()->options['settings']['builder_gallery']] . ')' );
4984 } else
4985 echo '-';
4986 break;
4987
4988 case 'source':
4989 $images = get_post_meta( $post_id, '_rl_images', true );
4990
4991 if ( ! empty( $images['menu_item'] ) && array_key_exists( $images['menu_item'], $this->tabs['images']['menu_items'] ) )
4992 echo esc_html( $this->tabs['images']['menu_items'][$images['menu_item']] );
4993 else
4994 echo '-';
4995 break;
4996 }
4997 }
4998 }
4999
5000 /**
5001 * Get size information for all currently-registered image sizes.
5002 *
5003 * @global array $_wp_additional_image_sizes
5004 *
5005 * @return array
5006 */
5007 public function get_image_sizes() {
5008 global $_wp_additional_image_sizes;
5009
5010 $sizes = [];
5011
5012 foreach ( get_intermediate_image_sizes() as $_size ) {
5013 if ( in_array( $_size, [ 'thumbnail', 'medium', 'medium_large', 'large' ] ) ) {
5014 $sizes[$_size]['width'] = get_option( "{$_size}_size_w" );
5015 $sizes[$_size]['height'] = get_option( "{$_size}_size_h" );
5016 $sizes[$_size]['crop'] = (bool) get_option( "{$_size}_crop" );
5017 } elseif ( isset( $_wp_additional_image_sizes[$_size] ) ) {
5018 $sizes[$_size] = [
5019 'width' => $_wp_additional_image_sizes[$_size]['width'],
5020 'height' => $_wp_additional_image_sizes[$_size]['height'],
5021 'crop' => $_wp_additional_image_sizes[$_size]['crop'],
5022 ];
5023 }
5024 }
5025
5026 return $sizes;
5027 }
5028
5029 /**
5030 * Get size information for a specific image size.
5031 *
5032 * @param string $size The image size for which to retrieve data.
5033 * @return false|array
5034 */
5035 public function get_image_size( $size ) {
5036 if ( isset( $this->sizes[$size] ) )
5037 return $this->sizes[$size];
5038 else
5039 return false;
5040 }
5041
5042 /**
5043 * Filter the admin post thumbnail HTML markup.
5044 *
5045 * @param string $content
5046 * @param int $post_id
5047 * @param int $thumbnail_id
5048 * @return string
5049 */
5050 public function admin_post_thumbnail_html( $content, $post_id, $thumbnail_id ) {
5051 if ( get_post_type( $post_id ) === 'rl_gallery' ) {
5052 $value = get_post_meta( $post_id, '_rl_featured_image', true );
5053 $frontend = function_exists( 'Responsive_Lightbox' ) ? Responsive_Lightbox()->frontend : null;
5054 if ( $frontend && method_exists( $frontend, 'sanitize_remote_image_url' ) )
5055 $value = $frontend->sanitize_remote_image_url( $value );
5056 $type = get_post_meta( $post_id, '_rl_featured_image_type', true );
5057 $type = ! empty( $type ) && in_array( $type, array( 'image', 'id', 'url' ) ) ? $type : 'image';
5058
5059 // force media library image
5060 if ( wp_doing_ajax() )
5061 $type = 'id';
5062 // post featured image is post thumbnail replacement?
5063 elseif ( $this->maybe_generate_thumbnail() === (int) $thumbnail_id ) {
5064 remove_filter( 'admin_post_thumbnail_html', array( $this, 'admin_post_thumbnail_html' ), 10 );
5065
5066 $content = _wp_post_thumbnail_html( 0, $post_id );
5067 }
5068
5069 $content = '
5070 <div class="rl-gallery-featured-image-options">
5071 <p class="howto">' . esc_html__( 'Select gallery featured image source:', 'responsive-lightbox' ) . '</p>
5072 <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 />
5073 <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 />
5074 <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>
5075 </div>
5076 <div class="rl-gallery-featured-image-select">
5077 <div class="rl-gallery-featured-image-select-id"' . ( $type === 'id' ? '' : ' style="display: none;"' ) . '>' . $content . '</div>
5078 <div class="rl-gallery-featured-image-select-url"' . ( $type === 'url' ? '' : ' style="display: none;"' ) . '>
5079 <p><input id="_rl_thumbnail_url" class="large-text" name="_rl_thumbnail_url" value="' . ( $type === 'url' ? esc_url( $value ) : '' ) . '" type="text" /></p>
5080 <p class="howto">' . esc_html__( 'Custom featured image URL', 'responsive-lightbox' ) . '</p>
5081 </div>
5082 <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>
5083 </div>
5084 ';
5085 }
5086
5087 return $content;
5088 }
5089
5090 /**
5091 * Modify the resulting HTML so that the feature image is set as a background property.
5092 *
5093 * @param string $html The HTML image tag.
5094 * @param int $post_id The post whose featured image is to be printed.
5095 * @param int $post_thumbnail_id The post thumbnail ID.
5096 * @param array|string $size The size of the featured image.
5097 * @param array $attr Additional attributes.
5098 * @return string
5099 */
5100 public function post_thumbnail_html( $html, $post_id = 0, $post_thumbnail_id = 0, $size = false, $attr = [] ) {
5101 if ( get_post_type( $post_id ) === 'rl_gallery' ) {
5102 // get featured image type
5103 $image_type = get_post_meta( $post_id, '_rl_featured_image_type', true );
5104
5105 // break if featured image type is media library
5106 if ( ! $image_type || $image_type == 'id' )
5107 return $html;
5108
5109 // get image source
5110 $image_src = $this->get_gallery_image_src( $this->get_featured_image_src( $post_id ) );
5111
5112 // no image?
5113 if ( empty( $image_src ) )
5114 return $html;
5115
5116 // add featured image as background in style tag
5117 $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;"';
5118
5119 $html = str_replace( 'src=', $style . ' src=', $html );
5120
5121 // fix the alt tag (if possible)
5122 $alt = $image_src['alt'];
5123
5124 if ( isset( $attr['alt'] ) )
5125 $alt = $attr['alt'];
5126
5127 if ( $alt ) {
5128 $html = str_replace( '/(alt=\'[^\']+\'\|alt="[^"]+")/', '', $html );
5129 $html = str_replace( 'src=', ' alt="' . esc_attr( $alt ) . '" src=', $html );
5130 }
5131 }
5132
5133 return $html;
5134 }
5135
5136 /**
5137 * Save the revision meta data. For example, used when saving a preview.
5138 *
5139 * @param int $revision_id
5140 * @return void
5141 */
5142 public function save_revision( $revision_id ) {
5143 // get revision
5144 $revision = get_post( $revision_id );
5145
5146 // get gallery ID
5147 $post_id = $revision->post_parent;
5148
5149 // is it rl gallery?
5150 if ( get_post_type( $post_id ) !== 'rl_gallery' )
5151 return;
5152
5153 $this->revision_id = $revision_id;
5154
5155 if ( ! wp_is_post_revision( $revision_id ) || ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || empty( $_POST['rl_gallery'] ) )
5156 return;
5157
5158 // save revisioned meta data
5159 $this->save_gallery( wp_unslash( $_POST ), $revision_id, true );
5160 }
5161
5162 /**
5163 * Update preview link.
5164 *
5165 * @param string $link Preview link
5166 * @return string
5167 */
5168 public function preview_post_link( $link ) {
5169 // add gallery revision id
5170 if ( property_exists( $this, 'revision_id' ) && ! is_null( $this->revision_id ) ) {
5171 $post_id = wp_get_post_parent_id( $this->revision_id );
5172
5173 // is it valid rl_gallery post?
5174 if ( $post_id && get_post_type( $post_id ) === 'rl_gallery' )
5175 return add_query_arg( 'rl_gallery_revision_id', $this->revision_id, $link );
5176 }
5177
5178 return $link;
5179 }
5180
5181 /**
5182 * Delete gallery revision at shutdown.
5183 *
5184 * @global object $post
5185 *
5186 * @return void
5187 */
5188 public function shutdown_preview() {
5189 // is it a frontend preview?
5190 if ( is_preview() && isset( $_GET['rl_gallery_revision_id'] ) ) {
5191 global $post;
5192
5193 // cast revision ID
5194 $revision_id = (int) $_GET['rl_gallery_revision_id'];
5195
5196 // is it a valid revision?
5197 if ( get_post_type( $post->ID ) === 'rl_gallery' && wp_is_post_revision( $revision_id ) === (int) $post->ID )
5198 wp_delete_post_revision( $revision_id );
5199 }
5200 }
5201
5202 /**
5203 * Filter gallery meta data needed for frontend gallery preview.
5204 *
5205 * @param mixed $value Meta value to filter
5206 * @param int $object_id
5207 * @param string $meta_key Meta key to filter a value for
5208 * @param bool $single Whether to return a single value
5209 * @return mixed
5210 */
5211 public function filter_preview_metadata( $value, $object_id, $meta_key, $single ) {
5212 // ignore other post types
5213 if ( get_post_type( $object_id ) !== 'rl_gallery' )
5214 return $value;
5215
5216 // get current post
5217 $post = get_post();
5218
5219 // prepare keys
5220 $keys = array( '_rl_featured_image_type', '_rl_featured_image', '_rl_images_count', '_thumbnail_id' );
5221
5222 // add other metakeys
5223 foreach ( array_keys( $this->tabs ) as $key ) {
5224 $keys[] = '_rl_' . $key;
5225 }
5226
5227 // restrict only to specified data
5228 if ( empty( $post ) || (int) $post->ID !== (int) $object_id || ! in_array( $meta_key, $keys, true ) || $post->post_type === 'revision' )
5229 return $value;
5230
5231 // grab the last autosave
5232 $preview = wp_get_post_autosave( $post->ID );
5233
5234 // invalid revision?
5235 if ( ! is_object( $preview ) )
5236 return $value;
5237
5238 // finally replace metadata
5239 return array( get_post_meta( $preview->ID, $meta_key, $single ) );
5240 }
5241 }
5242