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