PluginProbe ʕ •ᴥ•ʔ
Responsive Lightbox & Gallery / 2.4.5
Responsive Lightbox & Gallery v2.4.5
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-folders.php
responsive-lightbox / includes Last commit date
providers 3 years ago class-fast-image.php 3 years ago class-folders.php 3 years ago class-frontend.php 3 years ago class-galleries.php 3 years ago class-multilang.php 3 years ago class-remote-library-api.php 3 years ago class-remote-library.php 3 years ago class-settings.php 3 years ago class-tour.php 3 years ago class-welcome.php 3 years ago class-widgets.php 3 years ago functions.php 3 years ago
class-folders.php
1348 lines
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Responsive Lightbox folders class.
8 *
9 * @class Responsive_Lightbox_Folders
10 */
11 class Responsive_Lightbox_Folders {
12
13 private $mode = '';
14 private $rl_media_tag_terms = [];
15 private $term_counters = [
16 'keys' => [],
17 'values' => []
18 ];
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 * Class constructor.
37 *
38 * @param bool $read_only Whether plugin is in read only mode
39 * @return void
40 */
41 public function __construct( $read_only = false ) {
42 // set instance
43 Responsive_Lightbox()->folders = $this;
44
45 // allow to load old taxonomies even in read only mode
46 add_action( 'wp_ajax_rl-folders-load-old-taxonomies', [ $this, 'load_old_taxonomies' ] );
47
48 if ( $read_only )
49 return;
50
51 // actions
52 add_action( 'init', [ $this, 'detect_library_mode' ], 11 );
53 add_action( 'restrict_manage_posts', [ $this, 'restrict_manage_posts' ] );
54 add_action( 'wp_enqueue_media', [ $this, 'add_library_scripts' ] );
55 add_action( 'admin_enqueue_scripts', [ $this, 'add_library_scripts' ] );
56 add_action( 'pre-upload-ui', [ $this, 'pre_upload_ui' ] );
57 add_action( 'post-upload-ui', [ $this, 'post_upload_ui' ] );
58 add_action( 'add_attachment', [ $this, 'add_attachment' ] );
59 add_action( 'wp_ajax_save-attachment-compat', [ $this, 'ajax_save_attachment_compat' ], 0 );
60 add_action( 'wp_ajax_rl-folders-delete-term', [ $this, 'delete_term' ] );
61 add_action( 'wp_ajax_rl-folders-rename-term', [ $this, 'rename_term' ] );
62 add_action( 'wp_ajax_rl-folders-add-term', [ $this, 'add_term' ] );
63 add_action( 'wp_ajax_rl-folders-move-term', [ $this, 'move_term' ] );
64 add_action( 'wp_ajax_rl-folders-move-attachments', [ $this, 'move_attachments' ] );
65
66 // filters
67 add_filter( 'admin_body_class', [ $this, 'admin_body_class' ] );
68 add_filter( 'parse_query', [ $this, 'parse_query' ] );
69 add_filter( 'ajax_query_attachments_args', [ $this, 'ajax_query_attachments_args' ] );
70 add_filter( 'attachment_fields_to_edit', [ $this, 'attachment_fields_to_edit' ], 10, 2 );
71 add_filter( 'rl_count_attachments', [ $this, 'count_attachments' ], 10 );
72 }
73
74 /**
75 * Load previously used media taxonomies via AJAX.
76 *
77 * @return void
78 */
79 public function load_old_taxonomies() {
80 // no data?
81 if ( ! isset( $_POST['taxonomies'], $_POST['nonce'] ) )
82 wp_send_json_error();
83
84 // invalid taxonomies format?
85 if ( ! is_array( $_POST['taxonomies'] ) )
86 wp_send_json_error();
87
88 // invalid nonce?
89 if ( ! ctype_alnum( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'rl-folders-ajax-taxonomies-nonce' ) )
90 wp_send_json_error();
91
92 // get all possible (current and previous) taxonomies
93 $fields = $this->get_taxonomies();
94
95 // any results?
96 if ( ! empty( $fields ) ) {
97 // remove main taxonomy
98 if ( ( $key = array_search( 'rl_media_folder', $fields, true ) ) !== false )
99 unset( $fields[$key] );
100
101 // remove media tags
102 if ( ( $key = array_search( 'rl_media_tag', $fields, true ) ) !== false )
103 unset( $fields[$key] );
104
105 // sanitize taxonomies
106 $taxonomies = array_map( 'santize_key', $_POST['taxonomies'] );
107
108 foreach ( $taxonomies as $taxonomy ) {
109 // remove available taxonomy
110 if ( ( $key = array_search( $taxonomy, $fields, true ) ) !== false )
111 unset( $fields[$key] );
112 }
113 }
114
115 // send taxonomies, reindex them to avoid casting to an object in js
116 wp_send_json_success( [ 'taxonomies' => array_values( $fields ) ] );
117
118 }
119
120 /**
121 * Detect library mode (list or grid).
122 *
123 * @global string $pagenow
124 *
125 * @return void
126 */
127 public function detect_library_mode() {
128 global $pagenow;
129
130 if ( $pagenow === 'upload.php' ) {
131 // available modes
132 $modes = [ 'grid', 'list' ];
133
134 // sanitize mode
135 if ( isset( $_GET['mode'] ) )
136 $mode = sanitize_key( $_GET['mode'] );
137 else
138 $mode = '';
139
140 // check mode
141 if ( ! ( $mode && ctype_lower( $mode ) && in_array( $mode, $modes, true ) ) ) {
142 // get user mode
143 $user_mode = (string) get_user_option( 'media_library_mode' );
144
145 // valid user mode?
146 if ( in_array( $user_mode, $modes, true ) )
147 $mode = $user_mode;
148 // default wp mode
149 else
150 $mode = 'grid';
151 }
152
153 // store mode
154 $this->mode = $mode;
155 }
156
157 if ( $pagenow === 'upload.php' || wp_doing_ajax() ) {
158 $this->rl_media_tag_terms = get_terms(
159 [
160 'taxonomy' => 'rl_media_tag',
161 'hide_empty' => false,
162 'orderby' => 'name',
163 'order' => 'asc',
164 'number' => 0,
165 'fields' => 'id=>name',
166 'hierarchical' => false
167 ]
168 );
169 }
170 }
171
172 /**
173 * Admin body classes.
174 *
175 * @global string $pagenow
176 *
177 * @param array $classes Admin body classes
178 * @return array
179 */
180 public function admin_body_class( $classes ) {
181 global $pagenow;
182
183 if ( $pagenow === 'upload.php' ) {
184 // append class
185 $classes .= ' rl-folders-upload-' . $this->mode . '-mode';
186 }
187
188 return $classes;
189 }
190
191 /**
192 * Get folders dropdown HTML.
193 *
194 * @param string $taxonomy Folders taxonomy
195 * @param string $selected Folders taxonomy ID
196 * @return string
197 */
198 private function get_folders( $taxonomy, $selected = 0 ) {
199 // get only 1 term to check if taxonomy is empty
200 $any_terms = get_terms(
201 [
202 'taxonomy' => $taxonomy,
203 'hide_empty' => false,
204 'fields' => 'ids',
205 'hierarchical' => false,
206 'number' => 1
207 ]
208 );
209
210 // prepare dropdown categories parameters
211 $args = [
212 'orderby' => 'name',
213 'order' => 'asc',
214 'show_option_all' => __( 'Root Folder', 'responsive-lightbox' ),
215 'show_count' => false,
216 'hide_empty' => false,
217 'hierarchical' => true,
218 'hide_if_empty' => false,
219 'echo' => false,
220 'selected' => (int) $selected,
221 'id' => 'rl_folders_upload_files',
222 'name' => 'rl_folders_upload_files_term_id',
223 'taxonomy' => $taxonomy
224 ];
225
226 // no terms?
227 if ( ! is_wp_error( $any_terms ) && empty( $any_terms ) ) {
228 $args['show_option_none'] = __( 'Root Folder', 'responsive-lightbox' );
229 $args['option_none_value'] = 0;
230 }
231
232 return wp_dropdown_categories( $args );
233 }
234
235 /**
236 * Add filter to add media folder id to the uploader
237 *
238 * @return void
239 */
240 public function pre_upload_ui() {
241 add_filter( 'upload_post_params', [ $this, 'upload_post_params' ] );
242 }
243
244 /**
245 * Add media folder id param to the uploader.
246 *
247 * @param array $params Plupload parameters
248 * @return array
249 */
250 public function upload_post_params( $params ) {
251 $params['rl_folders_upload_files_term_id'] = 0;
252
253 return $params;
254 }
255
256 /**
257 * Display dropdown at media upload UI screen.
258 *
259 * @return void
260 */
261 public function post_upload_ui() {
262 // get taxonomy
263 $taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];
264
265 // get only 1 term to check if taxonomy is empty
266 $any_terms = get_terms(
267 [
268 'taxonomy' => $taxonomy,
269 'hide_empty' => false,
270 'fields' => 'ids',
271 'hierarchical' => false,
272 'number' => 1
273 ]
274 );
275
276 // prepare dropdown categories parameters
277 $args = [
278 'orderby' => 'name',
279 'order' => 'asc',
280 'show_option_all' => __( 'Root Folder', 'responsive-lightbox' ),
281 'show_count' => false,
282 'hide_empty' => false,
283 'hierarchical' => true,
284 'hide_if_empty' => false,
285 'echo' => false,
286 'selected' => isset( $_GET[$taxonomy] ) ? (int) $_GET[$taxonomy] : 0,
287 'id' => 'rl_folders_upload_files',
288 'name' => 'rl_folders_upload_files_term_id',
289 'taxonomy' => $taxonomy
290 ];
291
292 // no terms?
293 if ( ! is_wp_error( $any_terms ) && empty( $any_terms ) ) {
294 $args['show_option_none'] = __( 'Root Folder', 'responsive-lightbox' );
295 $args['option_none_value'] = 0;
296 }
297
298 // display select
299 echo '<p><label>' . esc_html__( 'Upload files to', 'responsive-lightbox' ) . ': ' . wp_kses( wp_dropdown_categories( $args ), $this->allowed_select_html ) . '</label></p>';
300 }
301
302 /**
303 * Assign attachment to given term.
304 *
305 * @param int $post_id Current attachment ID
306 * @return void
307 */
308 public function add_attachment( $post_id ) {
309 if ( isset( $_POST['rl_folders_upload_files_term_id'] ) ) {
310 // cast term id
311 $term_id = (int) $_POST['rl_folders_upload_files_term_id'];
312
313 // get taxonomy
314 $taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];
315
316 // valid term?
317 if ( is_array( term_exists( $term_id, $taxonomy ) ) )
318 wp_set_object_terms( $post_id, $term_id, $taxonomy, false );
319 }
320 }
321
322 /**
323 * Add filterable dropdown to media library.
324 *
325 * @global string $pagenow
326 *
327 * @return void
328 */
329 public function restrict_manage_posts() {
330 global $pagenow;
331
332 if ( $pagenow === 'upload.php' ) {
333 // get taxonomy
334 $taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];
335
336 $html = wp_dropdown_categories(
337 [
338 'orderby' => 'name',
339 'order' => 'asc',
340 'id' => 'media-attachment-rl-folders-filters',
341 'show_option_all' => __( 'All Files', 'responsive-lightbox' ),
342 'show_count' => false,
343 'hide_empty' => false,
344 'hierarchical' => true,
345 'selected' => ( isset( $_GET[$taxonomy] ) ? (int) $_GET[$taxonomy] : 0 ),
346 'name' => $taxonomy,
347 'taxonomy' => $taxonomy,
348 'hide_if_empty' => true,
349 'echo' => false
350 ]
351 );
352
353 if ( $html === '' )
354 echo '<select name="' . esc_attr( $taxonomy ) . '" id="media-attachment-rl-folders-filters" class="postform"><option>' . esc_html__( 'All Files', 'responsive-lightbox' ) . '</option></select> ';
355 else
356 echo wp_kses( $html, $this->allowed_select_html );
357 }
358 }
359
360 /**
361 * Change query to adjust taxonomy if needed.
362 *
363 * @global string $pagenow
364 *
365 * @param object $query WP Query
366 * @return object
367 */
368 public function parse_query( $query ) {
369 global $pagenow;
370
371 // get taxonomy
372 $taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];
373
374 if ( $pagenow === 'upload.php' && isset( $_GET[$taxonomy] ) ) {
375 // get tax query
376 $tax_query = $query->get( 'tax_query' );
377
378 if ( empty( $tax_query ) || ! is_array( $tax_query ) )
379 $tax_query = [];
380
381 // -1 === root, 0 === all files, >0 === term_id
382 $term_id = (int) $_GET[$taxonomy];
383
384 if ( $term_id !== 0 && ( $query->is_main_query() || empty( $query->query['rl_folders_root'] ) ) ) {
385 $tax = [
386 'taxonomy' => $taxonomy,
387 'field' => 'id'
388 ];
389
390 // root folder?
391 if ( $term_id === -1 ) {
392 $tax['terms'] = 0;
393 $tax['operator'] = 'NOT EXISTS';
394 $tax['include_children'] = false;
395 // specified term id
396 } else {
397 $tax['terms'] = $term_id;
398 $tax['include_children'] = false;
399 }
400
401 // add new tax query
402 $tax_query[] = [ 'relation' => 'AND', $tax ];
403
404 // set new tax query
405 $query->set( 'tax_query', $tax_query );
406 }
407 }
408
409 return $query;
410 }
411
412 /**
413 * Change AJAX query parameters to adjust taxonomy in the media library if needed.
414 *
415 * @param array $query Query arguments
416 * @return array
417 */
418 public function ajax_query_attachments_args( $query ) {
419 // get taxonomy
420 $taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];
421
422 if ( isset( $_POST['query'][$taxonomy] ) ) {
423 $term_id = sanitize_key( $_POST['query'][$taxonomy] );
424
425 if ( $term_id === 'all' )
426 return $query;
427
428 $term_id = (int) $term_id;
429
430 if ( $term_id < 0 )
431 return $query;
432
433 if ( empty( $query['tax_query'] ) || ! is_array( $query['tax_query'] ) )
434 $query['tax_query'] = [];
435
436 $query['tax_query'][] = [
437 'relation' => 'AND',
438 [
439 'taxonomy' => $taxonomy,
440 'field' => 'id',
441 'terms' => $term_id,
442 'include_children' => ( ! ( isset( $_POST['query']['include_children'] ) && $_POST['query']['include_children'] === 'false' ) ),
443 'operator' => ( $term_id === 0 ? 'NOT EXISTS' : 'IN' )
444 ]
445 ];
446 }
447
448 return $query;
449 }
450
451 /**
452 * Filter the array of attachment fields that are displayed when editing an attachment.
453 *
454 * @param array $fields Attachment fields
455 * @param object $post Post object
456 * @return array
457 */
458 public function attachment_fields_to_edit( $fields, $post ) {
459 if ( wp_doing_ajax() ) {
460 // get main instance
461 $rl = Responsive_Lightbox();
462
463 // get taxonomy option
464 $taxonomy = $rl->options['folders']['media_taxonomy'];
465
466 // get taxonomy object
467 $tax = (array) get_taxonomy( $taxonomy );
468
469 if ( ! empty( $tax ) ) {
470 if ( ! $tax['public'] || ! $tax['show_ui'] )
471 return $fields;
472
473 if ( empty( $tax['args'] ) )
474 $tax['args'] = [];
475
476 $ids = wp_get_post_terms( $post->ID, $taxonomy, [ 'fields' => 'ids' ] );
477
478 // get select HTML
479 $dropdown = wp_dropdown_categories(
480 [
481 'orderby' => 'name',
482 'order' => 'asc',
483 'show_option_none' => __( 'Root Folder', 'responsive-lightbox' ),
484 'show_option_all' => false,
485 'show_count' => false,
486 'hide_empty' => false,
487 'hierarchical' => true,
488 'selected' => ( ! empty( $ids ) ? reset( $ids ) : 0 ),
489 'name' => $taxonomy . '_term',
490 'taxonomy' => $taxonomy,
491 'hide_if_empty' => false,
492 'echo' => false
493 ]
494 );
495
496 $tax['input'] = 'html';
497 $tax['html'] = wp_kses( $dropdown, $this->allowed_select_html );
498
499 $fields[$taxonomy] = $tax;
500 }
501
502 if ( $rl->options['folders']['media_tags'] && taxonomy_exists( 'rl_media_tag' ) ) {
503 // get taxonomy object
504 $tax = (array) get_taxonomy( 'rl_media_tag' );
505
506 if ( ! empty( $tax ) ) {
507 if ( ! $tax['public'] || ! $tax['show_ui'] )
508 return $fields;
509
510 if ( empty( $tax['args'] ) )
511 $tax['args'] = [];
512
513 $tags_html = '';
514
515 // get terms
516 $tags = wp_get_post_terms( $post->ID, 'rl_media_tag', [ 'fields' => 'id=>name' ] );
517
518 // valid terms?
519 if ( ! is_wp_error( $tags ) && ! empty( $tags ) ) {
520 foreach ( $tags as $tag_name ) {
521 $tags_html .= '<option value="' . esc_attr( $tag_name ) . '" selected="selected">' . esc_html( $tag_name ) . '</li>';
522 }
523 } else
524 $tags = [];
525
526 // update input
527 $tax['input'] = 'html';
528
529 // $tags_html is already escaped here
530 $tax['html'] = '
531 <select class="rl-media-tag-select2" multiple="multiple" name="attachments[' . (int) $post->ID . '][rl_media_tag]">
532 ' . $tags_html . '
533 </select>';
534
535 // update taxonomy
536 $fields['rl_media_tag'] = $tax;
537 }
538 }
539 }
540
541 return $fields;
542 }
543
544 /**
545 * Assign new term IDs to given attachment ID via AJAX in modal attachment edit screen.
546 *
547 * @return void
548 */
549 function ajax_save_attachment_compat() {
550 // no attachment id?
551 if ( ! isset( $_REQUEST['id'] ) )
552 wp_send_json_error();
553
554 $id = (int) $_REQUEST['id'];
555
556 // invalid id?
557 if ( $id <= 0 )
558 wp_send_json_error();
559
560 // no valid data?
561 if ( empty( $_REQUEST['attachments'][$id] ) || ! is_array( $_REQUEST['attachments'][$id] ) )
562 wp_send_json_error();
563
564 // no sanitization like in wordpress core: wp_ajax_save_attachment_compat() function
565 $attachment_data = $_REQUEST['attachments'][$id];
566
567 // check nonce
568 check_ajax_referer( 'update-post_' . $id, 'nonce' );
569
570 if ( ! current_user_can( 'edit_post', $id ) )
571 wp_send_json_error();
572
573 // get post
574 $post = get_post( $id, ARRAY_A );
575
576 if ( empty( $post ) || $post['post_type'] !== 'attachment' )
577 wp_send_json_error();
578
579 // update attachment data if needed
580 $post = apply_filters( 'attachment_fields_to_save', $post, $attachment_data );
581
582 if ( isset( $post['errors'] ) )
583 wp_send_json_error();
584
585 // update attachment
586 wp_update_post( $post );
587
588 // get taxonomy
589 $taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];
590
591 // first if needed?
592 if ( isset( $attachment_data[$taxonomy] ) )
593 wp_set_object_terms( $id, (int) reset( array_map( 'trim', $attachment_data[$taxonomy] ) ), $taxonomy, false );
594 elseif ( isset( $_REQUEST[$taxonomy . '_term'] ) )
595 wp_set_object_terms( $id, (int) $_REQUEST[$taxonomy . '_term'], $taxonomy, false );
596 else
597 wp_set_object_terms( $id, '', $taxonomy, false );
598
599 // check media tags
600 if ( isset( $attachment_data['rl_media_tag'] ) && is_string( $attachment_data['rl_media_tag'] ) ) {
601 $media_tags = explode( ',', $attachment_data['rl_media_tag'] );
602
603 if ( ! empty( $media_tags ) && is_array( $media_tags ) )
604 $media_tags = array_filter( array_map( 'sanitize_title', $media_tags ) );
605
606 // any media tags?
607 if ( ! empty( $media_tags ) )
608 wp_set_object_terms( $id, $media_tags, 'rl_media_tag', false );
609 else
610 wp_set_object_terms( $id, '', 'rl_media_tag', false );
611 }
612
613 // get attachment data
614 $attachment = wp_prepare_attachment_for_js( $id );
615
616 // invalid attachment?
617 if ( ! $attachment )
618 wp_send_json_error();
619
620 // finally send success
621 wp_send_json_success( $attachment );
622 }
623
624 /**
625 * AJAX action to delete term.
626 *
627 * @return void
628 */
629 public function delete_term() {
630 // no data?
631 if ( ! isset( $_POST['term_id'], $_POST['nonce'], $_POST['children'] ) )
632 wp_send_json_error();
633
634 // invalid nonce?
635 if ( ! ctype_alnum( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'rl-folders-ajax-library-nonce' ) )
636 wp_send_json_error();
637
638 // sanitize term id
639 $term_id = (int) $_POST['term_id'];
640
641 if ( $term_id <= 0 )
642 wp_send_json_error();
643
644 // get taxonomy
645 $taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];
646
647 $remove_children = (int) $_POST['children'];
648
649 // delete children?
650 if ( $remove_children === 1 ) {
651 // get term children
652 $children = get_term_children( $term_id, $taxonomy );
653
654 // found any children?
655 if ( ! empty( $children ) && ! is_wp_error( $children ) ) {
656 // reverse array to delete terms with no children first
657 foreach ( array_reverse( $children ) as $child_id ) {
658 // delete child
659 wp_delete_term( $child_id, $taxonomy );
660 }
661 }
662 }
663
664 // delete parent
665 if ( is_wp_error( wp_delete_term( $term_id, $taxonomy ) ) )
666 wp_send_json_error();
667 else
668 wp_send_json_success( $this->get_folders( $taxonomy ) );
669 }
670
671 /**
672 * AJAX action to assign new parent of the term.
673 *
674 * @return void
675 */
676 public function move_term() {
677 // no data?
678 if ( ! isset( $_POST['parent_id'], $_POST['term_id'], $_POST['nonce'] ) )
679 wp_send_json_error();
680
681 // invalid nonce?
682 if ( ! ctype_alnum( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'rl-folders-ajax-library-nonce' ) )
683 wp_send_json_error();
684
685 // get taxonomy
686 $taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];
687
688 // update term
689 $update = wp_update_term( (int) $_POST['term_id'], $taxonomy, [ 'parent' => (int) $_POST['parent_id'] ] );
690
691 // error?
692 if ( is_wp_error( $update ) )
693 wp_send_json_error();
694 else
695 wp_send_json_success( $this->get_folders( $taxonomy ) );
696 }
697
698 /**
699 * AJAX action to add new term.
700 *
701 * @return void
702 */
703 public function add_term() {
704 // no data?
705 if ( ! isset( $_POST['parent_id'], $_POST['name'], $_POST['nonce'] ) )
706 wp_send_json_error();
707
708 // invalid nonce?
709 if ( ! ctype_alnum( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'rl-folders-ajax-library-nonce' ) )
710 wp_send_json_error();
711
712 // get taxonomy
713 $taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];
714
715 // prepare data
716 $original_slug = $slug = sanitize_title( $_POST['name'] );
717 $parent_id = (int) $_POST['parent_id'];
718
719 // get all term slugs
720 $terms = get_terms(
721 [
722 'taxonomy' => $taxonomy,
723 'hide_empty' => false,
724 'number' => 0,
725 'fields' => 'id=>slug',
726 'hierarchical' => true
727 ]
728 );
729
730 // any terms?
731 if ( ! is_wp_error( $terms ) && is_array( $terms ) && ! empty( $terms ) ) {
732 $i = 2;
733
734 // slug already exists? create unique one
735 while ( in_array( $slug, $terms, true ) ) {
736 $slug = $original_slug . '-' . $i ++;
737 }
738 }
739
740 // add new term, name is sanitized inside wp_insert_term with sanitize_term function
741 $term = wp_insert_term(
742 $_POST['name'],
743 $taxonomy,
744 [
745 'parent' => $parent_id,
746 'slug' => $slug
747 ]
748 );
749
750 // error?
751 if ( is_wp_error( $term ) )
752 wp_send_json_error();
753
754 $term = get_term( $term['term_id'], $taxonomy );
755
756 // error?
757 if ( is_wp_error( $term ) )
758 wp_send_json_error();
759 else {
760 wp_send_json_success(
761 [
762 'name' => $term->name,
763 'term_id' => $term->term_id,
764 'url' => admin_url( 'upload.php?mode=' . $this->mode . '&' . $taxonomy . '=' . $term->term_id ),
765 'select' => $this->get_folders( $taxonomy, $term->term_id )
766 ]
767 );
768 }
769 }
770
771 /**
772 * AJAX action to rename term.
773 *
774 * @return void
775 */
776 public function rename_term() {
777 // no data?
778 if ( ! isset( $_POST['term_id'], $_POST['name'], $_POST['nonce'] ) )
779 wp_send_json_error();
780
781 // invalid nonce?
782 if ( ! ctype_alnum( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'rl-folders-ajax-library-nonce' ) )
783 wp_send_json_error();
784
785 // sanitize term id
786 $term_id = (int) $_POST['term_id'];
787
788 if ( $term_id <= 0 )
789 wp_send_json_error();
790
791 // get taxonomy
792 $taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];
793
794 // update term, name is sanitized inside wp_update_term with sanitize_term function
795 $update = wp_update_term( $term_id, $taxonomy, [ 'name' => $_POST['name'] ] );
796
797 // error?
798 if ( is_wp_error( $update ) )
799 wp_send_json_error();
800
801 $term = get_term( $term_id, $taxonomy );
802
803 // error?
804 if ( is_wp_error( $term ) )
805 wp_send_json_error();
806 else {
807 wp_send_json_success(
808 [
809 'name' => $term->name,
810 'select' => $this->get_folders( $taxonomy, $term_id )
811 ]
812 );
813 }
814 }
815
816 /**
817 * AJAX action to assign new term to attachments.
818 *
819 * @return void
820 */
821 public function move_attachments() {
822 // no data?
823 if ( ! isset( $_POST['attachment_ids'], $_POST['old_term_id'], $_POST['new_term_id'], $_POST['nonce'] ) )
824 wp_send_json_error();
825
826 // invalid nonce?
827 if ( ! ctype_alnum( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'rl-folders-ajax-library-nonce' ) )
828 wp_send_json_error();
829
830 // not empty attachment ids array?
831 if ( empty( $_POST['attachment_ids'] ) || ! is_array( $_POST['attachment_ids'] ) )
832 wp_send_json_error();
833
834 // prepare data
835 $ids = $all_terms = [];
836 $attachments = [
837 'success' => [],
838 'failure' => [],
839 'duplicated' => []
840 ];
841
842 // filter unwanted data
843 $ids = array_unique( array_filter( array_map( 'intval', $_POST['attachment_ids'] ) ) );
844
845 // no ids?
846 if ( empty( $ids ) )
847 wp_send_json_error();
848
849 // prepare term ids
850 $old_term_id = (int) $_POST['old_term_id'];
851 $new_term_id = (int) $_POST['new_term_id'];
852
853 // get taxonomy
854 $taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];
855
856 // moving to root folder?
857 if ( $new_term_id === 0 ) {
858 foreach ( $ids as $id ) {
859 // get attachment term ids
860 $all_terms[$id] = wp_get_object_terms( $id, $taxonomy, [ 'fields' => 'ids' ] );
861
862 // remove all terms assigned to attachment
863 if ( ! is_wp_error( wp_set_object_terms( $id, null, $taxonomy, false ) ) )
864 $attachments['success'][] = $id;
865 else
866 $attachments['failure'][] = $id;
867 }
868 } else {
869 foreach ( $ids as $id ) {
870 // get attachment term ids
871 $terms = wp_get_object_terms( $id, $taxonomy, [ 'fields' => 'ids' ] );
872
873 // got terms?
874 if ( ! is_wp_error( $terms ) ) {
875 // save existing term (attachment already assigned to this term)
876 if ( in_array( $new_term_id, $terms, true ) )
877 $attachments['duplicated'][] = $id;
878
879 // update attachment's term
880 if ( ! is_wp_error( wp_set_object_terms( $id, $new_term_id, $taxonomy, false ) ) )
881 $attachments['success'][] = $id;
882 else
883 $attachments['failure'][] = $id;
884 }
885 }
886 }
887
888 if ( empty( $attachments['success'] ) )
889 wp_send_json_error();
890 else {
891 wp_send_json_success(
892 [
893 'attachments' => $attachments,
894 'terms' => $all_terms
895 ]
896 );
897 }
898 }
899
900 /**
901 * Change wp_list_categories HTML link.
902 *
903 * @param array $matches Matched elements
904 * @return string
905 */
906 public function replace_folders_href( $matches ) {
907 // get taxonomy
908 $taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];
909
910 // set 'all files' folder
911 $term_id = -1;
912 $url_term_id = 0;
913
914 // any matches?
915 if ( ! empty( $matches[1] ) ) {
916 $params = parse_url( html_entity_decode( urldecode( $matches[1] ) ) );
917
918 if ( isset( $params['query'] ) ) {
919 // parse query string
920 parse_str( $params['query'], $atts );
921
922 if ( isset( $atts['term'] ) ) {
923 // get term
924 $term = get_term_by( 'slug', $atts['term'], $taxonomy );
925
926 // valid term?
927 if ( $term !== false ) {
928 $this->term_counters['keys'][] = $term->term_id;
929
930 // set term id
931 $url_term_id = $term_id = $term->term_id;
932 }
933 }
934 }
935 }
936
937 // escape url early
938 return 'href="' . esc_url( apply_filters( 'rl_folders_media_folder_url', add_query_arg( [ 'mode' => $this->mode, $taxonomy => $url_term_id ] ), $matches, $this->mode, $url_term_id ) ) . '" data-term_id="' . (int) $term_id . '"';
939 }
940
941 /**
942 * Change wp_list_categories HTML link by adding attachment counter.
943 *
944 * @param array $matches Matched elements
945 * @return string
946 */
947 public function replace_folders_count( $matches ) {
948 if ( isset( $matches[1] ) ) {
949 $count = (int) str_replace( [ ' ', '&nbsp;' ], '', $matches[1] );
950 $this->term_counters['values'][] = $count;
951
952 return ' (' . $count . ')</a>';
953 }
954
955 return '</a>';
956 }
957
958 /**
959 * Change wp_list_categories HTML output by adding jsTree attributes if needed.
960 *
961 * @param array $matches Matched elements
962 * @return string
963 */
964 public function open_folders( $matches ) {
965 if ( isset( $matches[0] ) ) {
966 // open parent term
967 if ( isset( $matches[0] ) && strpos( $matches[0], 'current-cat-ancestor' ) !== false )
968 return $matches[0] . ' data-jstree=\'{ "opened": true }\'';
969
970 // select current term
971 if ( strpos( $matches[0], 'current-cat' ) !== false )
972 return $matches[0] . ' data-jstree=\'{ "selected": true }\'';
973 }
974 }
975
976 /**
977 * Enqueue all needed scripts and styles for media library and modal screens.
978 *
979 * @global string $pagenow
980 * @global object $wp_list_table
981 * @global array $_wp_admin_css_colors
982 *
983 * @param string $page Current page similar to $pagenow depends on from which filter function was called
984 * @return void
985 */
986 public function add_library_scripts( $page ) {
987 // count how many times function was executed, allow this only once
988 static $run = 0;
989
990 // allow only wp media scripts (empty $page), upload.php or media-new.php
991 if ( ! ( ( $page === '' || $page === 'upload.php' || $page === 'media-new.php' ) && $run < 1 ) )
992 return;
993
994 global $pagenow;
995
996 $run++;
997
998 // change page for wp_enqueue_media
999 if ( $page === '' ) {
1000 if ( $pagenow === 'upload.php' )
1001 $page = 'upload.php';
1002 else
1003 $page = 'media';
1004 }
1005
1006 // get main instance
1007 $rl = Responsive_Lightbox();
1008
1009 // include select2 styles
1010 wp_enqueue_style( 'responsive-lightbox-admin-select2', RESPONSIVE_LIGHTBOX_URL . '/assets/select2/select2' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.css', [], $rl->defaults['version'] );
1011
1012 // filterable media folders taxonomy
1013 $taxonomy = get_taxonomy( $rl->options['folders']['media_taxonomy'] );
1014
1015 // no taxonomy? it should be available here, updated in init_folders method
1016 if ( $taxonomy === false )
1017 return;
1018
1019 // main script dependencies
1020 $dependencies = [ 'jquery', 'underscore', 'jquery-ui-draggable', 'jquery-ui-droppable', 'media-models', 'tags-suggest' ];
1021
1022 // create folder counters
1023 $counters = [];
1024
1025 if ( $page !== 'media' ) {
1026 // prepare variables
1027 $no_items = '';
1028 $childless = false;
1029
1030 // include styles
1031 wp_enqueue_style( 'responsive-lightbox-folders-admin-css', RESPONSIVE_LIGHTBOX_URL . '/css/admin-folders.css' );
1032 wp_enqueue_style( 'responsive-lightbox-folders-perfect-scrollbar', RESPONSIVE_LIGHTBOX_URL . '/assets/perfect-scrollbar/perfect-scrollbar' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.css' );
1033 wp_enqueue_style( 'responsive-lightbox-folders-jstree', RESPONSIVE_LIGHTBOX_URL . '/assets/jstree/themes/default/style' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.css' );
1034
1035 // get color scheme global
1036 global $_wp_admin_css_colors;
1037
1038 // set default color;
1039 $color = '0,160,210';
1040
1041 if ( ! empty( $_wp_admin_css_colors ) ) {
1042 // get current admin color scheme name
1043 $current_color_scheme = get_user_option( 'admin_color' );
1044
1045 if ( empty( $current_color_scheme ) )
1046 $current_color_scheme = 'fresh';
1047
1048 // color exists? some schemes don't have 4 colors
1049 if ( isset( $_wp_admin_css_colors[$current_color_scheme] ) && property_exists( $_wp_admin_css_colors[$current_color_scheme], 'colors' ) && isset( $_wp_admin_css_colors[$current_color_scheme]->colors[3] ) ) {
1050 // convert color
1051 $rgb = $rl->hex2rgb( $_wp_admin_css_colors[$current_color_scheme]->colors[3] );
1052
1053 // valid color?
1054 if ( $rgb !== false )
1055 $color = implode( ',', $rgb );
1056 }
1057 }
1058
1059 // $color is already validated, no escaping
1060 wp_add_inline_style(
1061 'responsive-lightbox-folders-jstree',
1062 '#rl-folders-tree-container .jstree .rl-folders-state-active.rl-folders-state-hover {
1063 background: #fff !important;
1064 }
1065 #rl-folders-tree-container .jstree-container-ul .jstree-wholerow-clicked,
1066 #rl-folders-tree-container .jstree-container-ul:not(.jstree-wholerow-ul) .jstree-clicked {
1067 background: rgba(' . esc_attr( $color ) . ', 0.15);
1068 }
1069 #rl-folders-tree-container .jstree-container-ul .jstree-wholerow-hovered,
1070 #rl-folders-tree-container .jstree-container-ul:not(.jstree-wholerow-ul) .jstree-hovered {
1071 background: rgba(' . esc_attr( $color ) . ', 0.05);
1072 }'
1073 );
1074
1075 // list categories parameters
1076 $categories = [
1077 'orderby' => 'name',
1078 'order' => 'asc',
1079 'show_count' => true,
1080 'show_option_all' => '',
1081 'show_option_none' => '',
1082 'use_desc_for_title' => false,
1083 'title_li' => '',
1084 'hide_empty' => false,
1085 'hierarchical' => true,
1086 'taxonomy' => $taxonomy->name,
1087 'hide_title_if_empty' => true,
1088 'echo' => false
1089 ];
1090
1091 // get current term id
1092 $term_id = isset( $_GET[$taxonomy->name] ) ? (int) $_GET[$taxonomy->name] : 0;
1093
1094 // list mode?
1095 if ( $this->mode === 'list' ) {
1096 // get global wp list table instance
1097 global $wp_list_table;
1098
1099 // empty instance?
1100 if ( is_null( $wp_list_table ) )
1101 $wp_list_table = _get_list_table( 'WP_Media_List_Table' );
1102
1103 // start buffering
1104 ob_start();
1105
1106 // display "no media" table row
1107 echo '<tr class="no-items"><td class="colspanchange" colspan="' . (int) $wp_list_table->get_column_count() . '">';
1108
1109 $wp_list_table->no_items();
1110
1111 echo '</td></tr>';
1112
1113 // save "no media" table row
1114 $no_items = ob_get_contents();
1115
1116 // clear the buffer
1117 ob_end_clean();
1118
1119 // valid term?
1120 if ( $term_id > 0 ) {
1121 $children = get_term_children( $term_id, $taxonomy->name );
1122
1123 // found any children?
1124 $childless = ! ( ! empty( $children ) && ! is_wp_error( $children ) );
1125 }
1126 }
1127
1128 // set current term id
1129 if ( $term_id > 0 )
1130 $categories['current_category'] = $term_id;
1131
1132 // hide filter for grid
1133 if ( $this->mode !== 'list' ) {
1134 wp_add_inline_style(
1135 'responsive-lightbox-folders-admin-css',
1136 '#media-attachment-rl-folders-filters { display: none; }
1137 .media-modal-content .media-frame select.attachment-filters {
1138 max-width: 100%;
1139 min-width: auto;
1140 }'
1141 );
1142 }
1143
1144 // get taxonomy html output
1145 $html = wp_list_categories( $categories );
1146
1147 if ( $html !== '' ) {
1148 // fix for urls
1149 $html = preg_replace_callback( '/href=(?:\'|")(.*?)(?:\'|")/', [ $this, 'replace_folders_href' ], $html );
1150
1151 // fix for counters
1152 $html = preg_replace_callback( '/<\/a> \(((?:\d+|&nbsp;)+)\)/', [ $this, 'replace_folders_count' ], $html );
1153
1154 // open all needed folders at start
1155 if ( $term_id > 0 )
1156 $html = preg_replace_callback( '/class="cat-item cat-item-(\d+)(?:[a-z\s0-9-]+)?"/', [ $this, 'open_folders' ], $html );
1157
1158 // check whether counters are valid
1159 if ( ! ( empty( $this->term_counters['keys'] ) || empty( $this->term_counters['values'] ) || count( $this->term_counters['keys'] ) !== count( $this->term_counters['values'] ) ) ) {
1160 //@TODO counters are supposed to be used in JS but not implemented yet
1161 // update folder counters
1162 $counters = array_combine( $this->term_counters['keys'], $this->term_counters['values'] );
1163 }
1164 }
1165
1166 // root folder query
1167 $root_query = new WP_Query(
1168 apply_filters(
1169 'rl_root_folder_query_args',
1170 [
1171 'rl_folders_root' => true,
1172 'posts_per_page' => -1,
1173 'post_type' => 'attachment',
1174 'post_status' => 'inherit,private',
1175 'fields' => 'ids',
1176 'no_found_rows' => false,
1177 'tax_query' => [
1178 [
1179 'relation' => 'AND',
1180 [
1181 'taxonomy' => $taxonomy->name,
1182 'field' => 'id',
1183 'terms' => 0,
1184 'include_children' => false,
1185 'operator' => 'NOT EXISTS'
1186 ]
1187 ]
1188 ]
1189 ]
1190 )
1191 );
1192
1193 // set number of all attachments
1194 $counters[-1] = (int) apply_filters( 'rl_count_attachments', 0 );
1195
1196 // set number of root attachments (not categorized)
1197 $counters[0] = (int) $root_query->post_count;
1198
1199 $html = '
1200 <ul>
1201 <li class="cat-item cat-item-all"' . ( $term_id === 0 ? ' data-jstree=\'{ "selected": true }\'' : '' ) . '>
1202 <a href="' . esc_url( apply_filters( 'rl_folders_media_folder_url', add_query_arg( [ 'mode' => $this->mode, $taxonomy->name => 0 ] ), null, $this->mode, 0 ) ) . '" data-term_id="all">' . esc_html__( 'All Files', 'responsive-lightbox' ) . ' (' . (int) $counters[-1] . ')</a>
1203 </li>
1204 <li class="cat-item cat-item-0" data-jstree=\'{ "opened": true' . ( $term_id === -1 ? ', "selected": true ' : '' ) . ' }\'>
1205 <a href="' . esc_url( apply_filters( 'rl_folders_media_folder_url', add_query_arg( [ 'mode' => $this->mode, $taxonomy->name => -1 ] ), null, $this->mode, -1 ) ) . '" data-term_id="0">' . esc_html__( 'Root Folder', 'responsive-lightbox' ) . ' (' . (int) $counters[0] . ')</a>
1206 <ul>' . $html . '</ul>
1207 </li>
1208 </ul>';
1209
1210 // register scripts
1211 wp_register_script( 'responsive-lightbox-folders-jstree', RESPONSIVE_LIGHTBOX_URL . '/assets/jstree/jstree' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', [], $rl->defaults['version'], false );
1212 wp_register_script( 'responsive-lightbox-folders-perfect-scrollbar', RESPONSIVE_LIGHTBOX_URL . '/assets/perfect-scrollbar/perfect-scrollbar' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', [], $rl->defaults['version'], false );
1213
1214 $dependencies[] = 'responsive-lightbox-folders-jstree';
1215 $dependencies[] = 'responsive-lightbox-folders-perfect-scrollbar';
1216 }
1217
1218 wp_enqueue_script( 'responsive-lightbox-admin-select2', RESPONSIVE_LIGHTBOX_URL . '/assets/select2/select2.full' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', [ 'jquery' ], $rl->defaults['version'], false );
1219
1220 wp_enqueue_script( 'responsive-lightbox-folders-admin', RESPONSIVE_LIGHTBOX_URL . '/js/admin-folders.js', $dependencies, $rl->defaults['version'], false );
1221
1222 if ( $page === 'media' ) {
1223 // prepare script data
1224 $script_data = [
1225 'taxonomy' => $taxonomy->name,
1226 'page' => $page,
1227 'root' => esc_html__( 'Root Folder', 'responsive-lightbox' ),
1228 'terms' => wp_dropdown_categories(
1229 [
1230 'orderby' => 'name',
1231 'order' => 'asc',
1232 'show_option_all' => esc_html__( 'All Files', 'responsive-lightbox' ),
1233 'show_count' => false,
1234 'hide_empty' => false,
1235 'hierarchical' => true,
1236 'selected' => ( isset( $_GET[$taxonomy->name] ) ? (int) $_GET[$taxonomy->name] : 0 ),
1237 'name' => $taxonomy->name,
1238 'taxonomy' => $taxonomy->name,
1239 'hide_if_empty' => true,
1240 'echo' => false
1241 ]
1242 )
1243 ];
1244 } else {
1245 // prepare script data
1246 $script_data = [
1247 'remove_children' => $rl->options['folders']['folders_removal'],
1248 'wholerow' => $rl->options['folders']['jstree_wholerow'],
1249 'theme' => 'default',
1250 'counters' => $counters,
1251 'no_media_items' => $no_items,
1252 'taxonomy' => $taxonomy->name,
1253 'page' => $page,
1254 'root' => esc_html__( 'Root Folder', 'responsive-lightbox' ),
1255 'all_terms' => esc_html__( 'All Files', 'responsive-lightbox' ),
1256 'new_folder' => esc_html__( 'New Folder', 'responsive-lightbox' ),
1257 'delete_term' => esc_html__( 'Are you sure you want to delete this folder?', 'responsive-lightbox' ),
1258 'delete_terms' => esc_html__( 'Are you sure you want to delete this folder with all subfolders?', 'responsive-lightbox' ),
1259 'nonce' => wp_create_nonce( 'rl-folders-ajax-library-nonce' ),
1260 'terms' => wp_dropdown_categories(
1261 [
1262 'orderby' => 'name',
1263 'order' => 'asc',
1264 'show_option_all' => esc_html__( 'All Files', 'responsive-lightbox' ),
1265 'show_count' => false,
1266 'hide_empty' => false,
1267 'hierarchical' => true,
1268 'selected' => ( isset( $_GET[$taxonomy->name] ) ? (int) $_GET[$taxonomy->name] : 0 ),
1269 'name' => $taxonomy->name,
1270 'taxonomy' => $taxonomy->name,
1271 'hide_if_empty' => true,
1272 'echo' => false
1273 ]
1274 ),
1275 'template' => '
1276 <div id="rl-folders-tree-container">
1277 <div class="media-toolbar wp-filter">
1278 <div class="view-switch rl-folders-action-links">
1279 <a href="#" title="' . esc_attr( $taxonomy->labels->add_new_item ) . '" class="dashicons dashicons-plus rl-folders-add-new-folder' . ( $this->mode === 'list' && ( $term_id === -1 || $term_id > 0 ) ? '' : ' disabled-link' ) . '"></a>
1280 <a href="#" title="' . esc_attr( sprintf( __( 'Save new %s', 'responsive-lightbox' ), $taxonomy->labels->singular_name ) ) . '" class="dashicons dashicons-yes rl-folders-save-new-folder" style="display: none;"></a>
1281 <a href="#" title="' . esc_attr( sprintf( __( 'Cancel adding new %s', 'responsive-lightbox' ), $taxonomy->labels->singular_name ) ) . '" class="dashicons dashicons-no rl-folders-cancel-new-folder" style="display: none;"></a>
1282 <a href="#" title="' . esc_attr( $taxonomy->labels->edit_item ) . '" class="dashicons dashicons-edit rl-folders-rename-folder' . ( $this->mode === 'list' && $term_id > 0 ? '' : ' disabled-link' ) . '"></a>
1283 <a href="#" title="' . esc_attr( sprintf( __( 'Save %s', 'responsive-lightbox' ), $taxonomy->labels->singular_name ) ) . '" class="dashicons dashicons-yes rl-folders-save-folder" style="display: none;"></a>
1284 <a href="#" title="' . esc_attr( sprintf( __( 'Cancel renaming %s', 'responsive-lightbox' ), $taxonomy->labels->singular_name ) ) . '" class="dashicons dashicons-no rl-folders-cancel-folder" style="display: none;"></a>
1285 <a href="#" title="' . esc_attr( sprintf( __( 'Delete %s', 'responsive-lightbox' ), $taxonomy->labels->singular_name ) ) . '" class="dashicons dashicons-trash rl-folders-delete-folder' . ( $this->mode === 'list' && $term_id > 0 ? '' : ' disabled-link' ) . '"></a>
1286 <a href="#" title="' . esc_attr( sprintf( __( 'Expand %s', 'responsive-lightbox' ), $taxonomy->labels->singular_name ) ) . '" class="dashicons dashicons-arrow-down-alt2 rl-folders-expand-folder' . ( $this->mode === 'list' && ! $childless && ( $term_id === -1 || $term_id > 0 ) ? '' : ' disabled-link' ) . '"></a>
1287 <a href="#" title="' . esc_attr( sprintf( __( 'Collapse %s', 'responsive-lightbox' ), $taxonomy->labels->singular_name ) ) . '" class="dashicons dashicons-arrow-up-alt2 rl-folders-collapse-folder' . ( $this->mode === 'list' && ! $childless && ( $term_id === -1 || $term_id > 0 ) ? '' : ' disabled-link' ) . '"></a>
1288 </div>
1289 </div>
1290 <div id="rl-folders-tree">' . wp_kses_post( $html ) . '</div>
1291 </div>'
1292 ];
1293 }
1294
1295 wp_add_inline_script( 'responsive-lightbox-folders-admin', 'var rlFoldersArgs = ' . wp_json_encode( $script_data ) . ";\n", 'before' );
1296
1297 add_action( 'admin_print_styles', [ $this, 'admin_print_media_styles' ] );
1298 }
1299
1300 /**
1301 * CSS fix for media folders checklist.
1302 *
1303 * @return void
1304 */
1305 public function admin_print_media_styles() {
1306 echo '<style>.rl_media_folder li .selectit input[type="checkbox"] { margin: 0 3px; }</style>';
1307 }
1308
1309 /**
1310 * Count attachments.
1311 *
1312 * @return int
1313 */
1314 public function count_attachments() {
1315 $count = wp_count_posts( 'attachment' );
1316
1317 return (int) $count->inherit;
1318 }
1319
1320 /**
1321 * Get all previously used media taxonomies.
1322 *
1323 * @global object $wpdb
1324 *
1325 * @return array
1326 */
1327 public function get_taxonomies() {
1328 global $wpdb;
1329
1330 // query
1331 $fields = $wpdb->get_col( "
1332 SELECT DISTINCT tt.taxonomy
1333 FROM " . $wpdb->prefix . "term_taxonomy tt
1334 LEFT JOIN " . $wpdb->prefix . "term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
1335 LEFT JOIN " . $wpdb->prefix . "posts p ON p.ID = tr.object_id
1336 WHERE p.post_type = 'attachment'
1337 ORDER BY tt.taxonomy ASC"
1338 );
1339
1340 if ( ! empty( $fields ) ) {
1341 // remove polylang taxonomy
1342 if ( ( $key = array_search( 'language', $fields, true ) ) !== false )
1343 unset( $fields[$key] );
1344 }
1345
1346 return $fields;
1347 }
1348 }