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