PluginProbe ʕ •ᴥ•ʔ
Responsive Lightbox & Gallery / 2.5.3
Responsive Lightbox & Gallery v2.5.3
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 10 months ago class-frontend.php 10 months ago class-galleries.php 1 year ago class-multilang.php 2 years ago class-remote-library-api.php 1 year ago class-remote-library.php 1 year ago class-settings.php 1 year 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
5212 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 $image = esc_url( $featured_image );
3756 break;
3757
3758 // attachment id
3759 case 'id':
3760 $featured_image = (int) $featured_image;
3761 $image = wp_attachment_is_image( $featured_image ) ? $featured_image : $this->maybe_generate_thumbnail();
3762 break;
3763
3764 // first image
3765 case 'image':
3766 default:
3767 // get first gallery image
3768 $images = $this->get_gallery_images(
3769 $gallery_id,
3770 [
3771 'exclude' => true,
3772 'limit' => 1
3773 ]
3774 );
3775
3776 // set image data
3777 if ( $images )
3778 $image = reset( $images );
3779 else
3780 $image = 0;
3781 }
3782
3783 return apply_filters( 'rl_get_featured_image_src', $image, $gallery_id, $featured_image_type, $featured_image );
3784 }
3785
3786 /**
3787 * Get featured gallery attachments.
3788 *
3789 * @param array $args
3790 * @return array
3791 */
3792 public function gallery_query( $args ) {
3793 $attachments = [];
3794
3795 // get fields
3796 $fields = $this->fields['images']['featured'];
3797
3798 // force these settings
3799 $args['fields'] = 'ids';
3800 $args['tax_query'] = [];
3801 $args['meta_query'] = [];
3802 $args['author__in'] = [];
3803 $args['post_parent__in'] = [];
3804
3805 // get image source
3806 $args['image_source'] = isset( $args['image_source'] ) && array_key_exists( $args['image_source'], $fields['image_source']['options'] ) ? $args['image_source'] : $fields['image_source']['default'];
3807
3808 // get images per post
3809 $args['images_per_post'] = isset( $args['images_per_post'] ) ? absint( $args['images_per_post'] ) : $fields['images_per_post']['default'];
3810
3811 // get number of posts
3812 $args['number_of_posts'] = isset( $args['number_of_posts'] ) ? (int) $args['number_of_posts'] : $fields['number_of_posts']['default'];
3813
3814 // get all posts?
3815 if ( $args['number_of_posts'] <= 0 )
3816 $args['number_of_posts'] = -1;
3817
3818 // convert to wp query arg
3819 $args['posts_per_page'] = $args['number_of_posts'];
3820
3821 $args['order'] = isset( $args['order'] ) && array_key_exists( $args['order'], $fields['order']['options'] ) ? $args['order'] : $fields['order']['default'];
3822 $args['orderby'] = isset( $args['orderby'] ) && array_key_exists( $args['orderby'], $fields['orderby']['options'] ) ? $args['orderby'] : $fields['orderby']['default'];
3823 $args['offset'] = isset( $args['offset'] ) ? absint( $args['offset'] ) : 0;
3824
3825 $tax_queries = array(
3826 'post_format' => [],
3827 'post_term' => []
3828 );
3829
3830 $meta_queries = array(
3831 'page_template' => [],
3832 'image_source' => []
3833 );
3834
3835 // post type
3836 if ( ! empty( $args['post_type'] ) ) {
3837 // assign post types
3838 $post_types = $args['post_type'];
3839
3840 // clear post types
3841 $args['post_type'] = [];
3842
3843 foreach ( $post_types as $post_type ) {
3844 if ( array_key_exists( $post_type, $fields['post_type']['options'] ) )
3845 $args['post_type'][] = $post_type;
3846 }
3847 } else
3848 $args['post_type'] = $this->get_post_types( true );
3849
3850 // post status
3851 if ( ! empty( $args['post_status'] ) ) {
3852 // assign post statuses
3853 $post_statuses = $args['post_status'];
3854
3855 // clear post statuses
3856 $args['post_status'] = [];
3857
3858 foreach ( $post_statuses as $post_status ) {
3859 if ( array_key_exists( $post_status, $fields['post_status']['options'] ) )
3860 $args['post_status'][] = $post_status;
3861 }
3862 }
3863
3864 // post format
3865 if ( ! empty( $args['post_format'] ) ) {
3866 // assign post formats
3867 $post_formats = $args['post_format'];
3868
3869 foreach ( $post_formats as $post_format ) {
3870 if ( array_key_exists( $post_format, $fields['post_format']['options'] ) ) {
3871 // standard format?
3872 if ( $post_format === 'standard' ) {
3873 $tax_queries['post_format'][] = array(
3874 'relation' => 'OR',
3875 array(
3876 'taxonomy' => 'post_format',
3877 'field' => 'slug',
3878 'terms' => array( 'post-format-standard' )
3879 ),
3880 array(
3881 'taxonomy' => 'post_format',
3882 'field' => 'slug',
3883 'operator' => 'NOT EXISTS'
3884 )
3885 );
3886 } else {
3887 $tax_queries['post_format'][] = array(
3888 'taxonomy' => 'post_format',
3889 'field' => 'slug',
3890 'terms' => array( 'post-format-' . $post_format )
3891 );
3892 }
3893 }
3894 }
3895
3896 unset( $args['post_format'] );
3897 }
3898
3899 // page template
3900 if ( ! empty( $args['page_template'] ) ) {
3901 foreach ( $args['page_template'] as $page_template ) {
3902 if ( array_key_exists( $page_template, $fields['page_template']['options'] ) ) {
3903 if ( $page_template === 'default' ) {
3904 $meta_queries['page_template'][] = array(
3905 'relation' => 'OR',
3906 array(
3907 'key' => '_wp_page_template',
3908 'value' => 'default'
3909 ),
3910 array(
3911 'key' => '_wp_page_template',
3912 'value' => ''
3913 ),
3914 array(
3915 'key' => '_wp_page_template',
3916 'compare' => 'NOT EXISTS'
3917 )
3918 );
3919 } else {
3920 $meta_queries['page_template'][] = array(
3921 'key' => '_wp_page_template',
3922 'value' => $page_template
3923 );
3924 }
3925 }
3926 }
3927 }
3928
3929 // post author
3930 if ( ! empty( $args['post_author'] ) ) {
3931 foreach ( $args['post_author'] as $post_author ) {
3932 if ( array_key_exists( $post_author, $fields['post_author']['options'] ) )
3933 $args['author__in'][] = $post_author;
3934 }
3935 }
3936
3937 // page parent
3938 if ( ! empty( $args['page_parent'] ) ) {
3939 foreach ( $args['page_parent'] as $page_parent ) {
3940 if ( array_key_exists( $page_parent, $fields['page_parent']['options'] ) )
3941 $args['post_parent__in'][] = $page_parent;
3942 }
3943 }
3944
3945 // post term
3946 if ( ! empty( $args['post_term'] ) ) {
3947 $terms = [];
3948
3949 // get all terms
3950 if ( ! empty( $fields['post_term']['options'] ) ) {
3951 foreach ( $fields['post_term']['options'] as $tax => $data ) {
3952 $terms = array_merge( $terms, array_map( 'intval', array_keys( $data['terms'] ) ) );
3953 }
3954 }
3955
3956 foreach ( $args['post_term'] as $post_term ) {
3957 if ( in_array( $post_term, $terms ) ) {
3958 $term = get_term( $post_term );
3959
3960 $tax_queries['post_term'][] = array(
3961 'taxonomy' => $term->taxonomy,
3962 'field' => 'term_id',
3963 'terms' => (int) $post_term
3964 );
3965 }
3966 }
3967 }
3968
3969 switch ( $args['image_source'] ) {
3970 case 'thumbnails':
3971 $meta_queries['image_source'][] = array(
3972 'relation' => 'OR',
3973 array(
3974 'key' => '_thumbnail_id',
3975 'compare' => 'EXISTS'
3976 )
3977 );
3978 }
3979
3980 // any tax queries?
3981 if ( ! empty( $tax_queries['post_term'] ) || ! empty( $tax_queries['post_format'] ) ) {
3982 $args['tax_query'] = array( 'relation' => 'AND' );
3983
3984 if ( ! empty( $tax_queries['post_term'] ) )
3985 $args['tax_query'][] = array( 'relation' => 'OR' ) + $tax_queries['post_term'];
3986
3987 if ( ! empty( $tax_queries['post_format'] ) )
3988 $args['tax_query'][] = array( 'relation' => 'OR' ) + $tax_queries['post_format'];
3989 }
3990
3991 // any tax queries?
3992 if ( ! empty( $meta_queries['page_template'] ) || ! empty( $meta_queries['image_source'] ) ) {
3993 $args['meta_query'] = array( 'relation' => 'AND' );
3994
3995 if ( ! empty( $meta_queries['page_template'] ) )
3996 $args['meta_query'][] = array( 'relation' => 'OR', $meta_queries['page_template'] );
3997
3998 if ( ! empty( $meta_queries['image_source'] ) )
3999 $args['meta_query'][] = array( 'relation' => 'OR', $meta_queries['image_source'] );
4000 }
4001
4002 // get posts
4003 $query = new WP_Query( apply_filters( 'rl_gallery_query_args', $args ) );
4004
4005 // get attachments
4006 if ( $query->have_posts() )
4007 $attachments = $this->get_gallery_query_attachments( $query->posts, $args );
4008
4009 return $attachments;
4010 }
4011
4012 /**
4013 * Get query attachments.
4014 *
4015 * @param array $posts Post IDs, array or objects
4016 * @param array $args Additional arguments
4017 * @return array
4018 */
4019 public function get_gallery_query_attachments( $posts, $args ) {
4020 $attachments = [];
4021
4022 // any posts?
4023 if ( ! empty( $posts ) ) {
4024 switch ( $args['image_source'] ) {
4025 case 'thumbnails':
4026 $nop = count( $posts ) - 1;
4027
4028 foreach ( $posts as $number => $post_id ) {
4029 $attachment_id = (int) get_post_thumbnail_id( $post_id );
4030
4031 // real attachment?
4032 if ( wp_attachment_is_image( $attachment_id ) )
4033 $attachments[] = $attachment_id;
4034 else
4035 continue;
4036
4037 if ( $args['preview'] ) {
4038 $attachments = array_unique( $attachments );
4039 $noa = count( $attachments );
4040
4041 if ( ( $noa >= ( $args['preview_per_page'] * $args['preview_page'] ) ) || $nop === $number ) {
4042 $attachments = array_slice( $attachments, ( $args['preview_page'] - 1 ) * $args['preview_per_page'], $args['preview_per_page'], false );
4043
4044 break;
4045 }
4046 }
4047 }
4048 break;
4049
4050 case 'attached_images':
4051 $nop = count( $posts ) - 1;
4052
4053 foreach ( $posts as $number => $post_id ) {
4054 // get attached images, do not use get_attached_media here!
4055 $attachment_ids = (array) get_children(
4056 array(
4057 'post_parent' => $post_id,
4058 'post_status' => 'inherit',
4059 'post_type' => 'attachment',
4060 'post_mime_type' => 'image',
4061 'posts_per_page' => $args['images_per_post'],
4062 'order' => 'ASC',
4063 'orderby' => 'menu_order',
4064 'nopaging' => false,
4065 'page' => 1,
4066 'fields' => 'ids'
4067 )
4068 );
4069
4070 if ( $attachment_ids ) {
4071 foreach ( $attachment_ids as $attachment_id ) {
4072 if ( ! empty( $attachment_id ) ) {
4073 $attachments[] = $attachment_id;
4074 }
4075 }
4076 }
4077
4078 if ( $args['preview'] ) {
4079 $attachments = array_unique( $attachments );
4080 $noa = count( $attachments );
4081
4082 if ( ( $noa >= ( $args['preview_per_page'] * $args['preview_page'] ) ) || $nop === $number ) {
4083 $attachments = array_slice( $attachments, ( $args['preview_page'] - 1 ) * $args['preview_per_page'], $args['preview_per_page'], false );
4084
4085 break;
4086 }
4087 }
4088 }
4089 }
4090 }
4091
4092 return apply_filters( 'rl_get_gallery_query_attachments', array_unique( $attachments ), $posts, $args );
4093 }
4094
4095 /**
4096 * Load featured content query args.
4097 *
4098 * @global string $pagenow
4099 *
4100 * @return void
4101 */
4102 public function init_admin() {
4103 global $pagenow;
4104
4105 // check values
4106 $post = isset( $_GET['post'] ) ? (int) $_GET['post'] : 0;
4107 $post_id = isset( $_POST['post_ID'] ) ? (int) $_POST['post_ID'] : 0;
4108 $action = isset( $_POST['action'] ) ? sanitize_key( $_POST['action'] ) : '';
4109 $post_type = isset( $_POST['post_type'] ) ? sanitize_key( $_POST['post_type'] ) : '';
4110
4111 // prepare query arguments if needed
4112 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 ) ) )
4113 $this->fields['images']['featured'] = $this->prepare_featured_fields( $this->fields['images']['featured'] );
4114
4115 // add default thumbnail image if needed
4116 if ( Responsive_Lightbox()->options['builder']['gallery_builder'] && $pagenow === 'edit.php' && $post_type && $post_type === 'rl_gallery' )
4117 $this->maybe_generate_thumbnail();
4118 }
4119
4120 /**
4121 * Generate post thumbnail replacement.
4122 *
4123 * @return int
4124 */
4125 public function maybe_generate_thumbnail() {
4126 // get old attachment
4127 $thumbnail_id = get_posts(
4128 array(
4129 'name' => 'responsive-lightbox-thumbnail',
4130 'post_type' => 'attachment',
4131 'post_status' => 'inherit',
4132 'numberposts' => 1,
4133 'fields' => 'ids'
4134 )
4135 );
4136
4137 // no attachment?
4138 if ( empty( $thumbnail_id ) ) {
4139 // get new attachment
4140 $thumbnail_id = get_posts(
4141 array(
4142 'name' => 'responsive-lightbox-thumbnail',
4143 'post_type' => 'attachment',
4144 'post_status' => 'pending',
4145 'numberposts' => 1,
4146 'fields' => 'ids'
4147 )
4148 );
4149
4150 // no attachment?
4151 if ( empty( $thumbnail_id ) ) {
4152 // get upload directory data
4153 $wp_upload_dir = wp_upload_dir();
4154
4155 // get file path
4156 $filepath = str_replace( '\\', '/', RESPONSIVE_LIGHTBOX_PATH . 'images/responsive-lightbox-thumbnail.png' );
4157
4158 // get file name
4159 $filename = basename( $filepath );
4160
4161 // new filepath in upload dir
4162 $new_filepath = $wp_upload_dir['path'] . '/' . $filename;
4163
4164 // copty file to upload dir
4165 copy( $filepath, $new_filepath );
4166
4167 // get type of file
4168 $filetype = wp_check_filetype( $filename );
4169
4170 // force pending status for the attachment
4171 add_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
4172
4173 // insert attachment
4174 $thumbnail_id = wp_insert_attachment(
4175 array(
4176 'guid' => $wp_upload_dir['url'] . '/' . $filename,
4177 'post_mime_type' => $filetype['type'],
4178 'post_title' => preg_replace( '/\.[^.]+$/', '', $filename ),
4179 'post_content' => '',
4180 'post_parent' => 0,
4181 'post_status' => 'inherit'
4182 ),
4183 $new_filepath,
4184 0
4185 );
4186
4187 remove_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
4188
4189 // success?
4190 if ( $thumbnail_id ) {
4191 // make sure that this file is included
4192 require_once( ABSPATH . 'wp-admin/includes/image.php' );
4193
4194 // update database with generated metadata for the attachment
4195 wp_update_attachment_metadata( $thumbnail_id, wp_generate_attachment_metadata( $thumbnail_id, $new_filepath ) );
4196 }
4197 } else
4198 $thumbnail_id = $thumbnail_id[0];
4199 } else {
4200 // force pending status for the attachment
4201 add_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
4202
4203 $thumbnail_id = wp_update_post(
4204 array(
4205 'ID' => $thumbnail_id[0],
4206 'post_status' => 'pending'
4207 )
4208 );
4209
4210 remove_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
4211 }
4212
4213 return (int) $thumbnail_id;
4214 }
4215
4216 /**
4217 * Get video thumbnail replacement.
4218 *
4219 * @param int $post_id
4220 * @return int
4221 */
4222 public function get_video_thumbnail_id( $post_id ) {
4223 $thumbnail_id = 0;
4224
4225 // try to get video thumbnail
4226 $attachment_id = (int) get_post_thumbnail_id( $post_id );
4227
4228 // real attachment?
4229 if ( wp_attachment_is_image( $attachment_id ) )
4230 $thumbnail_id = $attachment_id;
4231
4232 // try to get default video poster image
4233 if ( ! $thumbnail_id ) {
4234 $thumbnail_id = get_posts(
4235 array(
4236 'name' => 'responsive-lightbox-video-thumbnail',
4237 'post_type' => 'attachment',
4238 'post_status' => 'inherit',
4239 'numberposts' => 1,
4240 'fields' => 'ids'
4241 )
4242 );
4243 }
4244
4245 // no attachment?
4246 if ( ! $thumbnail_id ) {
4247 // get new attachment
4248 $thumbnail_id = get_posts(
4249 array(
4250 'name' => 'responsive-lightbox-video-thumbnail',
4251 'post_type' => 'attachment',
4252 'post_status' => 'pending',
4253 'numberposts' => 1,
4254 'fields' => 'ids'
4255 )
4256 );
4257
4258 // no attachment?
4259 if ( ! $thumbnail_id ) {
4260 // get upload directory data
4261 $wp_upload_dir = wp_upload_dir();
4262
4263 // get file path
4264 $filepath = str_replace( '\\', '/', RESPONSIVE_LIGHTBOX_PATH . 'images/responsive-lightbox-video-thumbnail.png' );
4265
4266 // get file name
4267 $filename = basename( $filepath );
4268
4269 // new filepath in upload dir
4270 $new_filepath = $wp_upload_dir['path'] . '/' . $filename;
4271
4272 // copty file to upload dir
4273 copy( $filepath, $new_filepath );
4274
4275 // get type of file
4276 $filetype = wp_check_filetype( $filename );
4277
4278 // force pending status for the attachment
4279 add_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
4280
4281 // insert attachment
4282 $thumbnail_id = wp_insert_attachment(
4283 array(
4284 'guid' => $wp_upload_dir['url'] . '/' . $filename,
4285 'post_mime_type' => $filetype['type'],
4286 'post_title' => preg_replace( '/\.[^.]+$/', '', $filename ),
4287 'post_content' => '',
4288 'post_parent' => 0,
4289 'post_status' => 'inherit'
4290 ),
4291 $new_filepath,
4292 0
4293 );
4294
4295 remove_filter( 'wp_insert_attachment_data', array( $this, 'set_attachment_post_status' ) );
4296
4297 // success?
4298 if ( $thumbnail_id ) {
4299 // make sure that this file is included
4300 require_once( ABSPATH . 'wp-admin/includes/image.php' );
4301
4302 // update database with generated metadata for the attachment
4303 wp_update_attachment_metadata( $thumbnail_id, wp_generate_attachment_metadata( $thumbnail_id, $new_filepath ) );
4304 }
4305 } else
4306 $thumbnail_id = $thumbnail_id[0];
4307 }
4308
4309 return (int) $thumbnail_id;
4310 }
4311
4312 /**
4313 * Change status of new attachment thumbnail replacement.
4314 *
4315 * @param array $data
4316 * @return array
4317 */
4318 function set_attachment_post_status( $data ) {
4319 $data['post_status'] = 'pending';
4320
4321 return $data;
4322 }
4323
4324 /**
4325 * Prepare featured content fields.
4326 *
4327 * @param array $fields
4328 * @return array
4329 */
4330 public function prepare_featured_fields( $fields ) {
4331 foreach ( array( 'post_type', 'post_status', 'post_format', 'post_term', 'post_author', 'page_parent', 'page_template' ) as $option ) {
4332 $fields[$option]['options'] = $this->prepare_query_args( $option );
4333 }
4334
4335 return $fields;
4336 }
4337
4338 /**
4339 * Prepare values option list.
4340 *
4341 * @param string $type
4342 * @return array
4343 */
4344 public function prepare_query_args( $type = '' ) {
4345 $html = '';
4346
4347 switch( $type ) {
4348 case 'post_type':
4349 $data = $this->get_post_types();
4350 break;
4351
4352 case 'post_status':
4353 $data = $this->get_post_statuses();
4354 break;
4355
4356 case 'post_format':
4357 $data = $this->get_post_formats();
4358 break;
4359
4360 case 'post_term':
4361 $taxonomies = $this->get_taxonomies();
4362 $new_terms = [];
4363
4364 if ( ! empty( $taxonomies ) ) {
4365 foreach ( $taxonomies as $tax_id => $label ) {
4366 $terms = get_terms(
4367 array(
4368 'taxonomy' => $tax_id,
4369 'orderby' => 'name',
4370 'order' => 'ASC',
4371 'hide_empty' => false,
4372 'fields' => 'id=>name'
4373 )
4374 );
4375
4376 if ( ! empty( $terms ) )
4377 $new_terms[$tax_id] = array(
4378 'label' => $label,
4379 'terms' => $terms
4380 );
4381 }
4382 }
4383
4384 $data = $new_terms;
4385 break;
4386
4387 case 'post_author':
4388 $data = $this->get_users();
4389 break;
4390
4391 case 'page_parent':
4392 $parents = [];
4393 $hierarchical = get_post_types(
4394 array(
4395 'public' => true,
4396 'hierarchical' => true
4397 ),
4398 'objects',
4399 'and'
4400 );
4401
4402 if ( ! empty( $hierarchical ) ) {
4403 foreach ( $hierarchical as $post_type => $object ) {
4404 // get top level hierarchical posts
4405 $query = new WP_Query(
4406 array(
4407 'post_type' => $post_type,
4408 'post_status' => 'publish',
4409 'nopaging' => true,
4410 'posts_per_page' => -1,
4411 'orderby' => 'title',
4412 'order' => 'ASC',
4413 'suppress_filters' => false,
4414 'no_found_rows' => true,
4415 'cache_results' => false,
4416 'post_parent' => 0
4417 )
4418 );
4419
4420 if ( ! empty( $query->posts ) ) {
4421 foreach ( $query->posts as $post ) {
4422 $parents[$post->ID] = trim( $post->post_title ) === '' ? __( 'Untitled' ) : $post->post_title;
4423 }
4424 }
4425 }
4426 }
4427
4428 $data = $parents;
4429 break;
4430
4431 case 'page_template':
4432 $data = $this->get_page_templates();
4433 break;
4434
4435 default:
4436 $data = [];
4437 }
4438
4439 return apply_filters( 'rl_galleries_prepare_query_args', $data, $type );
4440 }
4441
4442 /**
4443 * Get public post types.
4444 *
4445 * @param bool $simple Which data should be returned
4446 * @param bool $skip Which post types should be skipped
4447 * @return array
4448 */
4449 public function get_post_types( $simple = false, $skip = [ 'attachment', 'rl_gallery' ] ) {
4450 $post_types = get_post_types(
4451 array(
4452 'public' => true
4453 ),
4454 'objects',
4455 'and'
4456 );
4457
4458 $data = [];
4459
4460 if ( ! empty( $post_types ) ) {
4461 foreach ( $post_types as $post_type => $cpt ) {
4462 // skip unwanted post types
4463 if ( in_array( $post_type, $skip, true ) )
4464 continue;
4465
4466 if ( $simple )
4467 $data[] = $post_type;
4468 else
4469 $data[$post_type] = $cpt->labels->singular_name;
4470 }
4471 }
4472
4473 if ( ! $simple )
4474 asort( $data );
4475
4476 return $data;
4477 }
4478
4479 /**
4480 * Get post statuses.
4481 *
4482 * @return array
4483 */
4484 public function get_post_statuses() {
4485 $post_statuses = get_post_stati();
4486
4487 asort( $post_statuses );
4488
4489 // remove inherit post status
4490 if ( isset( $post_statuses['inherit'] ) )
4491 unset( $post_statuses['inherit'] );
4492
4493 return $post_statuses;
4494 }
4495
4496 /**
4497 * Get post formats.
4498 *
4499 * @return array
4500 */
4501 public function get_post_formats() {
4502 $post_formats = array(
4503 'aside' => __( 'Aside' ),
4504 'audio' => __( 'Audio' ),
4505 'chat' => __( 'Chat' ),
4506 'gallery' => __( 'Gallery' ),
4507 'link' => __( 'Link' ),
4508 'photo' => __( 'Photo' ),
4509 'quote' => __( 'Quote' ),
4510 'standard' => __( 'Standard' ),
4511 'status' => __( 'Status' ),
4512 'video' => __( 'Video' )
4513 );
4514
4515 asort( $post_formats );
4516
4517 return $post_formats;
4518 }
4519
4520 /**
4521 * Get taxonomies.
4522 *
4523 * @return array
4524 */
4525 public function get_taxonomies() {
4526 $taxonomies = get_taxonomies(
4527 array(
4528 'public' => true
4529 ),
4530 'objects',
4531 'and'
4532 );
4533
4534 // remove post format
4535 if ( array_key_exists( 'post_format', $taxonomies ) )
4536 unset( $taxonomies['post_format'] );
4537
4538 // get main instance
4539 $rl = Responsive_Lightbox();
4540
4541 // remove gallery categories
4542 if ( $rl->options['builder']['categories'] && array_key_exists( 'rl_category', $taxonomies ) )
4543 unset( $taxonomies['rl_category'] );
4544
4545 // remove gallery tags
4546 if ( $rl->options['builder']['tags'] && array_key_exists( 'rl_tag', $taxonomies ) )
4547 unset( $taxonomies['rl_tag'] );
4548
4549 if ( $rl->options['folders']['active'] ) {
4550 // remove media folders categories
4551 unset( $taxonomies['rl_media_folder'] );
4552
4553 // remove custom media folders categories
4554 if ( $rl->options['folders']['media_taxonomy'] !== 'rl_media_folder' )
4555 unset( $taxonomies[$rl->options['folders']['media_taxonomy']] );
4556
4557 // remove media folders tags
4558 if ( $rl->options['folders']['media_tags'] )
4559 unset( $taxonomies['rl_media_tag'] );
4560 }
4561
4562 $data = [];
4563
4564 if ( ! empty( $taxonomies ) ) {
4565 foreach ( $taxonomies as $tax_id => $taxonomy ) {
4566 $data[$tax_id] = $taxonomy->labels->singular_name;
4567 }
4568 }
4569
4570 // sort taxonomies
4571 asort( $data );
4572
4573 return $data;
4574 }
4575
4576 /**
4577 * Get users.
4578 *
4579 * @return array
4580 */
4581 public function get_users() {
4582 $users = get_users(
4583 array(
4584 'fields' => array( 'ID', 'user_login' )
4585 )
4586 );
4587
4588 $data = [];
4589
4590 if ( ! empty( $users ) ) {
4591 foreach ( $users as $user ) {
4592 $data[(int) $user->ID] = $user->user_login;
4593 }
4594 }
4595
4596 asort( $data );
4597
4598 return $data;
4599 }
4600
4601 /**
4602 * Get page templates.
4603 *
4604 * @return array
4605 */
4606 public function get_page_templates() {
4607 $data = [];
4608 $page_templates = wp_get_theme()->get_page_templates();
4609
4610 if ( ! empty( $page_templates ) )
4611 asort( $page_templates );
4612
4613 $data = array_merge( array( 'default' => apply_filters( 'default_page_template_title', __( 'Default Template' ) ) ), $page_templates );
4614
4615 return $data;
4616 }
4617
4618 /**
4619 * Fix possible misplaced or hidden metaboxes do to old 'after_title' metabox and possibility to move internal metaboxes.
4620 *
4621 * @return void
4622 */
4623 public function clear_metaboxes( $screen ) {
4624 global $pagenow;
4625
4626 if ( ! ( ( $pagenow === 'post.php' || $pagenow === 'post-new.php' ) && ! empty( $screen->post_type ) && $screen->post_type === 'rl_gallery' && empty( $_POST['rl_gallery'] ) ) )
4627 return;
4628
4629 // get user id
4630 $user_id = get_current_user_id();
4631
4632 // get rl metaboxes
4633 $order = get_user_meta( $user_id, 'meta-box-order_rl_gallery', true );
4634
4635 // any metabox order? fix possible misplaced metaboxes
4636 if ( is_array( $order ) && ! empty( $order ) ) {
4637 // save metaboxes
4638 $_order = $order;
4639
4640 // default rl metaboxes
4641 $rl_boxes = [ 'responsive-gallery-images', 'responsive-gallery-config', 'responsive-gallery-design', 'responsive-gallery-paging', 'responsive-gallery-lightbox', 'responsive-gallery-misc' ];
4642
4643 foreach ( $_order as $group => $metaboxes ) {
4644 if ( $group === 'after_title' ) {
4645 // remove deprecated after_title metabox
4646 unset( $order['after_title'] );
4647 } elseif ( $metaboxes !== '' ) {
4648 $boxes = explode( ',', $metaboxes );
4649 $new_boxes = [];
4650
4651 foreach ( $boxes as $box ) {
4652 if ( ! in_array( $box, $rl_boxes, true ) )
4653 $new_boxes[] = $box;
4654 }
4655
4656 if ( ! empty( $new_boxes ) )
4657 $order[$group] = implode( ',', $new_boxes );
4658 else
4659 $order[$group] = '';
4660 }
4661 }
4662
4663 // remove default metaboxes storage
4664 if ( array_key_exists( 'responsive_lightbox_metaboxes', $order ) )
4665 unset( $order['responsive_lightbox_metaboxes'] );
4666
4667 // update usermeta to prevent issues with rl metaboxes
4668 if ( $order !== $_order )
4669 update_user_meta( $user_id, 'meta-box-order_rl_gallery', $order );
4670 }
4671 }
4672
4673 /**
4674 * Save gallery metadata.
4675 *
4676 * @param int $post_id
4677 * @param object $post
4678 * @param bool $update Whether existing post is being updated or not
4679 * @return void
4680 */
4681 public function save_post( $post_id, $post, $update ) {
4682 // check action
4683 $action = isset( $_GET['action'] ) ? sanitize_key( $_GET['action'] ) : '';
4684
4685 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'] ) )
4686 return;
4687
4688 // save gallery
4689 $this->save_gallery( wp_unslash( $_POST ), $post_id );
4690 }
4691
4692 /**
4693 * Save gallery preview metadata.
4694 *
4695 * @param array $post_data Gallery data
4696 * @param int $post_id
4697 * @param bool $preview Whether is it preview
4698 * @return void
4699 */
4700 public function save_gallery( $post_data, $post_id, $preview = false ) {
4701 // get gallery data
4702 $data = $post_data['rl_gallery'];
4703
4704 // prepare sanitized data
4705 $safedata = [];
4706
4707 // sanitize all fields
4708 foreach ( $this->fields as $tab_id => $menu_items ) {
4709 switch ( $tab_id ) {
4710 case 'config':
4711 // get main instance
4712 $rl = Responsive_Lightbox();
4713
4714 // add menu item
4715 $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'] );
4716
4717 // get default gallery fields
4718 $default_gallery_fields = $rl->frontend->get_default_gallery_fields();
4719
4720 // prepare fields
4721 if ( $menu_item === 'default' )
4722 $items = $default_gallery_fields;
4723 else {
4724 // assign settings and defaults
4725 $fields = $rl->settings->settings[$menu_item . '_gallery']['fields'];
4726 $defaults = $rl->defaults[$menu_item . '_gallery'];
4727
4728 // make a copy
4729 $fields_copy = $fields;
4730
4731 foreach ( $fields_copy as $field_id => $field ) {
4732 if ( $field['type'] === 'multiple' ) {
4733 foreach ( $field['fields'] as $subfield_id => $subfield ) {
4734 $fields[$field_id]['fields'][$subfield_id]['default'] = $defaults[$subfield_id];
4735 }
4736 } else
4737 $fields[$field_id]['default'] = $defaults[$field_id];
4738 }
4739
4740 $items = $rl->frontend->get_unique_fields( $default_gallery_fields, $fields );
4741 }
4742
4743 // sanitize fields
4744 $safedata = $this->sanitize_fields( $items, $data, $tab_id, $menu_item );
4745
4746 // add menu item
4747 $safedata[$tab_id]['menu_item'] = $menu_item;
4748 break;
4749
4750 default:
4751 // add menu item
4752 $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';
4753
4754 // sanitize fields
4755 $safedata = $this->sanitize_fields( $menu_items[$menu_item], $data, $tab_id, $menu_item );
4756
4757 // add menu item
4758 $safedata[$tab_id]['menu_item'] = $menu_item;
4759 }
4760
4761 $safedata[$tab_id] = apply_filters( 'rl_gallery_tab_metadata', $safedata[$tab_id], $tab_id );
4762
4763 // preview?
4764 if ( $preview )
4765 update_metadata( 'post', $post_id, '_rl_' . $tab_id, $safedata[$tab_id] );
4766 else
4767 update_post_meta( $post_id, '_rl_' . $tab_id, $safedata[$tab_id] );
4768 }
4769
4770 $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';
4771
4772 switch ( $featured_image_type ) {
4773 // custom url
4774 case 'url':
4775 $thumbnail_id = $this->maybe_generate_thumbnail();
4776 $featured_image = isset( $post_data['_rl_thumbnail_url'] ) ? esc_url_raw( $post_data['_rl_thumbnail_url'] ) : '';
4777 break;
4778
4779 // first image
4780 case 'image':
4781 $thumbnail_id = $this->maybe_generate_thumbnail();
4782 $featured_image = '';
4783 break;
4784
4785 // attachment id
4786 case 'id':
4787 default:
4788 $featured_image = $thumbnail_id = isset( $post_data['_thumbnail_id'] ) ? (int) $post_data['_thumbnail_id'] : 0;
4789 }
4790
4791 // preview?
4792 if ( $preview ) {
4793 update_metadata( 'post', $post_id, '_rl_featured_image_type', $featured_image_type );
4794 update_metadata( 'post', $post_id, '_rl_featured_image', $featured_image );
4795 update_metadata( 'post', $post_id, '_thumbnail_id', $thumbnail_id );
4796 } else {
4797 // update featured image
4798 update_post_meta( $post_id, '_rl_featured_image_type', $featured_image_type );
4799 update_post_meta( $post_id, '_rl_featured_image', $featured_image );
4800 update_post_meta( $post_id, '_thumbnail_id', $thumbnail_id );
4801
4802 // save number of images
4803 update_post_meta( $post_id, '_rl_images_count', $this->get_gallery_images_number( $post_id ) );
4804 }
4805
4806 // update post excerpt
4807 if ( isset( $safedata['misc']['options']['gallery_description'] ) ) {
4808 remove_action( 'save_post_rl_gallery', [ $this, 'save_post' ], 10, 3 );
4809
4810 $postdata = [
4811 'ID' => $post_id,
4812 'post_excerpt' => sanitize_textarea_field( $safedata['misc']['options']['gallery_description'] )
4813 ];
4814
4815 wp_update_post( $postdata );
4816
4817 add_action( 'save_post_rl_gallery', [ $this, 'save_post' ], 10, 3 );
4818 }
4819 }
4820
4821 /**
4822 * Check attachments IDs.
4823 *
4824 * @param array $attachments Attachment ID's
4825 * @param array $args
4826 * @return array
4827 */
4828 public function check_attachments( $attachments, $args = [] ) {
4829 // no attachments?
4830 if ( empty( $attachments ) || ! is_array( $attachments ) )
4831 return [];
4832
4833 // check providers support
4834 if ( ! empty( $args['providers'] ) )
4835 $embed = rl_current_lightbox_supports( $args['providers'], 'OR' );
4836 else
4837 $embed = false;
4838
4839 // no embed data?
4840 if ( ! $embed )
4841 $copy = array_map( 'intval', $attachments );
4842 else
4843 $copy = $attachments;
4844
4845 // check attachments
4846 foreach ( $attachments as $key => $attachment_id ) {
4847 // embed?
4848 if ( $embed && preg_match( '/^e\d+$/', $attachment_id ) === 1 ) {
4849 if ( ! in_array( $attachment_id, $args['embed_keys'], true ) )
4850 unset( $copy[$key] );
4851 // video support?
4852 } elseif ( rl_current_lightbox_supports( 'video' ) ) {
4853 // is it an image or video?
4854 if ( ! wp_attachment_is( 'video', $attachment_id ) && ! wp_attachment_is( 'image', $attachment_id ) )
4855 unset( $copy[$key] );
4856 // make sure it's integer
4857 elseif ( $embed )
4858 $copy[$key] = (int) $copy[$key];
4859 } else {
4860 // is it an image?
4861 if ( ! wp_attachment_is_image( $attachment_id ) )
4862 unset( $copy[$key] );
4863 // make sure it's integer
4864 elseif ( $embed )
4865 $copy[$key] = (int) $copy[$key];
4866 }
4867 }
4868
4869 return array_values( $copy );
4870 }
4871
4872 /**
4873 * Display shortcode metabox.
4874 *
4875 * @param object $post
4876 * @return void
4877 */
4878 public function shortcode_metabox( $post ) {
4879 echo '
4880 <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>
4881 <code class="rl-shortcode" data-number="0">[rl_gallery id=&quot;' . (int) $post->ID . '&quot;]</code>
4882 <p>' . esc_html__( 'You can also place this gallery into your template files by using the template tag below', 'responsive-lightbox' ) . ':</p>
4883 <code class="rl-shortcode" data-number="1">if ( function_exists( \'rl_gallery\' ) ) { rl_gallery( \'' . (int) $post->ID . '\' ); }</code>';
4884 }
4885
4886 /**
4887 * Add new gallery listing columns.
4888 *
4889 * @param array $columns
4890 * @return array
4891 */
4892 public function gallery_columns( $columns ) {
4893 // find title position
4894 $offset = array_search( 'title', array_keys( $columns ) );
4895
4896 // put image column before title
4897 $columns = array_merge(
4898 array_slice( $columns, 0, $offset ),
4899 array(
4900 'image' => esc_html__( 'Gallery', 'responsive-lightbox' )
4901 ),
4902 array_slice( $columns, $offset )
4903 );
4904
4905 // put new columns after title
4906 $columns = array_merge(
4907 array_slice( $columns, 0, $offset + 2 ),
4908 array(
4909 'shortcode' => esc_html__( 'Shortcode', 'responsive-lightbox' ),
4910 'type' => esc_html__( 'Type', 'responsive-lightbox' ),
4911 'source' => esc_html__( 'Source', 'responsive-lightbox' )
4912 ),
4913 array_slice( $columns, $offset + 2 )
4914 );
4915
4916 return $columns;
4917 }
4918
4919 /**
4920 * Add new gallery listing columns content.
4921 *
4922 * @global string $pagenow
4923 *
4924 * @param string $column_name
4925 * @param int $post_id
4926 * @return void
4927 */
4928 public function gallery_columns_content( $column_name, $post_id ) {
4929 global $pagenow;
4930
4931 if ( $pagenow === 'edit.php' ) {
4932 switch ( $column_name ) {
4933 case 'image':
4934 // get image data, based on gallery source type
4935 $image = $this->get_featured_image( $post_id, 'thumbnail' );
4936 $images_count = (int) get_post_meta( $post_id, '_rl_images_count', true );
4937
4938 // display count
4939 if ( ! empty( $image ) )
4940 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>';
4941 else
4942 echo '<span class="media-icon image-icon">' . wp_get_attachment_image( 0, array( 60, 60 ), true, array( 'alt' => '' ) ) . '</span>';
4943 break;
4944
4945 case 'shortcode':
4946 echo '<code>[rl_gallery id="' . (int) $post_id . '"]</code>';
4947 break;
4948
4949 case 'type':
4950 $config = get_post_meta( $post_id, '_rl_config', true );
4951
4952 if ( ! empty( $config['menu_item'] ) && array_key_exists( $config['menu_item'], $this->tabs['config']['menu_items'] ) ) {
4953 echo esc_html( $this->tabs['config']['menu_items'][$config['menu_item']] );
4954
4955 if ( $config['menu_item'] === 'default' )
4956 echo esc_html( ' (' . $this->tabs['config']['menu_items'][Responsive_Lightbox()->options['settings']['builder_gallery']] . ')' );
4957 } else
4958 echo '-';
4959 break;
4960
4961 case 'source':
4962 $images = get_post_meta( $post_id, '_rl_images', true );
4963
4964 if ( ! empty( $images['menu_item'] ) && array_key_exists( $images['menu_item'], $this->tabs['images']['menu_items'] ) )
4965 echo esc_html( $this->tabs['images']['menu_items'][$images['menu_item']] );
4966 else
4967 echo '-';
4968 break;
4969 }
4970 }
4971 }
4972
4973 /**
4974 * Get size information for all currently-registered image sizes.
4975 *
4976 * @global array $_wp_additional_image_sizes
4977 *
4978 * @return array
4979 */
4980 public function get_image_sizes() {
4981 global $_wp_additional_image_sizes;
4982
4983 $sizes = [];
4984
4985 foreach ( get_intermediate_image_sizes() as $_size ) {
4986 if ( in_array( $_size, [ 'thumbnail', 'medium', 'medium_large', 'large' ] ) ) {
4987 $sizes[$_size]['width'] = get_option( "{$_size}_size_w" );
4988 $sizes[$_size]['height'] = get_option( "{$_size}_size_h" );
4989 $sizes[$_size]['crop'] = (bool) get_option( "{$_size}_crop" );
4990 } elseif ( isset( $_wp_additional_image_sizes[$_size] ) ) {
4991 $sizes[$_size] = [
4992 'width' => $_wp_additional_image_sizes[$_size]['width'],
4993 'height' => $_wp_additional_image_sizes[$_size]['height'],
4994 'crop' => $_wp_additional_image_sizes[$_size]['crop'],
4995 ];
4996 }
4997 }
4998
4999 return $sizes;
5000 }
5001
5002 /**
5003 * Get size information for a specific image size.
5004 *
5005 * @param string $size The image size for which to retrieve data.
5006 * @return false|array
5007 */
5008 public function get_image_size( $size ) {
5009 if ( isset( $this->sizes[$size] ) )
5010 return $this->sizes[$size];
5011 else
5012 return false;
5013 }
5014
5015 /**
5016 * Filter the admin post thumbnail HTML markup.
5017 *
5018 * @param string $content
5019 * @param int $post_id
5020 * @param int $thumbnail_id
5021 * @return string
5022 */
5023 public function admin_post_thumbnail_html( $content, $post_id, $thumbnail_id ) {
5024 if ( get_post_type( $post_id ) === 'rl_gallery' ) {
5025 $value = get_post_meta( $post_id, '_rl_featured_image', true );
5026 $type = get_post_meta( $post_id, '_rl_featured_image_type', true );
5027 $type = ! empty( $type ) && in_array( $type, array( 'image', 'id', 'url' ) ) ? $type : 'image';
5028
5029 // force media library image
5030 if ( wp_doing_ajax() )
5031 $type = 'id';
5032 // post featured image is post thumbnail replacement?
5033 elseif ( $this->maybe_generate_thumbnail() === (int) $thumbnail_id ) {
5034 remove_filter( 'admin_post_thumbnail_html', array( $this, 'admin_post_thumbnail_html' ), 10 );
5035
5036 $content = _wp_post_thumbnail_html( 0, $post_id );
5037 }
5038
5039 $content = '
5040 <div class="rl-gallery-featured-image-options">
5041 <p class="howto">' . esc_html__( 'Select gallery featured image source:', 'responsive-lightbox' ) . '</p>
5042 <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 />
5043 <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 />
5044 <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>
5045 </div>
5046 <div class="rl-gallery-featured-image-select">
5047 <div class="rl-gallery-featured-image-select-id"' . ( $type === 'id' ? '' : ' style="display: none;"' ) . '>' . $content . '</div>
5048 <div class="rl-gallery-featured-image-select-url"' . ( $type === 'url' ? '' : ' style="display: none;"' ) . '>
5049 <p><input id="_rl_thumbnail_url" class="large-text" name="_rl_thumbnail_url" value="' . ( $type === 'url' ? esc_url( $value ) : '' ) . '" type="text" /></p>
5050 <p class="howto">' . esc_html__( 'Custom featured image URL', 'responsive-lightbox' ) . '</p>
5051 </div>
5052 <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>
5053 </div>
5054 ';
5055 }
5056
5057 return $content;
5058 }
5059
5060 /**
5061 * Modify the resulting HTML so that the feature image is set as a background property.
5062 *
5063 * @param string $html The HTML image tag.
5064 * @param int $post_id The post whose featured image is to be printed.
5065 * @param int $post_thumbnail_id The post thumbnail ID.
5066 * @param array|string $size The size of the featured image.
5067 * @param array $attr Additional attributes.
5068 * @return string
5069 */
5070 public function post_thumbnail_html( $html, $post_id = 0, $post_thumbnail_id = 0, $size = false, $attr = [] ) {
5071 if ( get_post_type( $post_id ) === 'rl_gallery' ) {
5072 // get featured image type
5073 $image_type = get_post_meta( $post_id, '_rl_featured_image_type', true );
5074
5075 // break if featured image type is media library
5076 if ( ! $image_type || $image_type == 'id' )
5077 return $html;
5078
5079 // get image source
5080 $image_src = $this->get_gallery_image_src( $this->get_featured_image_src( $post_id ) );
5081
5082 // no image?
5083 if ( empty( $image_src ) )
5084 return $html;
5085
5086 // add featured image as background in style tag
5087 $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;"';
5088
5089 $html = str_replace( 'src=', $style . ' src=', $html );
5090
5091 // fix the alt tag (if possible)
5092 $alt = $image_src['alt'];
5093
5094 if ( isset( $attr['alt'] ) )
5095 $alt = $attr['alt'];
5096
5097 if ( $alt ) {
5098 $html = str_replace( '/(alt=\'[^\']+\'\|alt="[^"]+")/', '', $html );
5099 $html = str_replace( 'src=', ' alt="' . esc_attr( $alt ) . '" src=', $html );
5100 }
5101 }
5102
5103 return $html;
5104 }
5105
5106 /**
5107 * Save the revision meta data. For example, used when saving a preview.
5108 *
5109 * @param int $revision_id
5110 * @return void
5111 */
5112 public function save_revision( $revision_id ) {
5113 // get revision
5114 $revision = get_post( $revision_id );
5115
5116 // get gallery ID
5117 $post_id = $revision->post_parent;
5118
5119 // is it rl gallery?
5120 if ( get_post_type( $post_id ) !== 'rl_gallery' )
5121 return;
5122
5123 $this->revision_id = $revision_id;
5124
5125 if ( ! wp_is_post_revision( $revision_id ) || ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || empty( $_POST['rl_gallery'] ) )
5126 return;
5127
5128 // save revisioned meta data
5129 $this->save_gallery( wp_unslash( $_POST ), $revision_id, true );
5130 }
5131
5132 /**
5133 * Update preview link.
5134 *
5135 * @param string $link Preview link
5136 * @return string
5137 */
5138 public function preview_post_link( $link ) {
5139 // add gallery revision id
5140 if ( property_exists( $this, 'revision_id' ) && ! is_null( $this->revision_id ) ) {
5141 $post_id = wp_get_post_parent_id( $this->revision_id );
5142
5143 // is it valid rl_gallery post?
5144 if ( $post_id && get_post_type( $post_id ) === 'rl_gallery' )
5145 return add_query_arg( 'rl_gallery_revision_id', $this->revision_id, $link );
5146 }
5147
5148 return $link;
5149 }
5150
5151 /**
5152 * Delete gallery revision at shutdown.
5153 *
5154 * @global object $post
5155 *
5156 * @return void
5157 */
5158 public function shutdown_preview() {
5159 // is it a frontend preview?
5160 if ( is_preview() && isset( $_GET['rl_gallery_revision_id'] ) ) {
5161 global $post;
5162
5163 // cast revision ID
5164 $revision_id = (int) $_GET['rl_gallery_revision_id'];
5165
5166 // is it a valid revision?
5167 if ( get_post_type( $post->ID ) === 'rl_gallery' && wp_is_post_revision( $revision_id ) === (int) $post->ID )
5168 wp_delete_post_revision( $revision_id );
5169 }
5170 }
5171
5172 /**
5173 * Filter gallery meta data needed for frontend gallery preview.
5174 *
5175 * @param mixed $value Meta value to filter
5176 * @param int $object_id
5177 * @param string $meta_key Meta key to filter a value for
5178 * @param bool $single Whether to return a single value
5179 * @return mixed
5180 */
5181 public function filter_preview_metadata( $value, $object_id, $meta_key, $single ) {
5182 // ignore other post types
5183 if ( get_post_type( $object_id ) !== 'rl_gallery' )
5184 return $value;
5185
5186 // get current post
5187 $post = get_post();
5188
5189 // prepare keys
5190 $keys = array( '_rl_featured_image_type', '_rl_featured_image', '_rl_images_count', '_thumbnail_id' );
5191
5192 // add other metakeys
5193 foreach ( array_keys( $this->tabs ) as $key ) {
5194 $keys[] = '_rl_' . $key;
5195 }
5196
5197 // restrict only to specified data
5198 if ( empty( $post ) || (int) $post->ID !== (int) $object_id || ! in_array( $meta_key, $keys, true ) || $post->post_type === 'revision' )
5199 return $value;
5200
5201 // grab the last autosave
5202 $preview = wp_get_post_autosave( $post->ID );
5203
5204 // invalid revision?
5205 if ( ! is_object( $preview ) )
5206 return $value;
5207
5208 // finally replace metadata
5209 return array( get_post_meta( $preview->ID, $meta_key, $single ) );
5210 }
5211 }
5212