PluginProbe ʕ •ᴥ•ʔ
Responsive Lightbox & Gallery / 2.5.4
Responsive Lightbox & Gallery v2.5.4
2.7.8 trunk 1.0.0 1.0.1 1.0.1.1 1.0.2 1.0.3 1.0.4 1.1.0 1.1.1 1.1.2 1.2.0 1.2.1 1.2.2 1.2.3 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.4.0 1.4.0.1 1.4.1 1.4.11 1.4.12 1.4.13 1.4.14 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.6.0 1.6.1 1.6.10 1.6.11 1.6.12 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 2.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.1 2.2.0 2.2.1 2.2.2 2.2.3 2.2.3.1 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.3.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.4.8 2.4.9 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.6.0 2.6.1 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7
responsive-lightbox / includes / class-folders.php
responsive-lightbox / includes Last commit date
providers 1 year ago class-fast-image.php 2 years ago class-folders.php 7 months ago class-frontend.php 7 months ago class-galleries.php 7 months ago class-multilang.php 2 years ago class-remote-library-api.php 1 year ago class-remote-library.php 1 year ago class-settings.php 1 year ago class-tour.php 2 years ago class-welcome.php 2 years ago class-widgets.php 2 years ago functions.php 3 years ago
class-folders.php
1354 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 $name = sanitize_text_field( $_POST['name'] );
718 $parent_id = (int) $_POST['parent_id'];
719
720 // empty name?
721 if ( $original_slug === '' || $name === '' )
722 wp_send_json_error();
723
724 // get all term slugs
725 $terms = get_terms(
726 [
727 'taxonomy' => $taxonomy,
728 'hide_empty' => false,
729 'number' => 0,
730 'fields' => 'id=>slug',
731 'hierarchical' => true
732 ]
733 );
734
735 // any terms?
736 if ( ! is_wp_error( $terms ) && is_array( $terms ) && ! empty( $terms ) ) {
737 $i = 2;
738
739 // slug already exists? create unique one
740 while ( in_array( $slug, $terms, true ) ) {
741 $slug = $original_slug . '-' . $i ++;
742 }
743 }
744
745 // add new term, name is sanitized inside wp_insert_term with sanitize_term function
746 $term = wp_insert_term(
747 $name,
748 $taxonomy,
749 [
750 'parent' => $parent_id,
751 'slug' => $slug
752 ]
753 );
754
755 // error?
756 if ( is_wp_error( $term ) )
757 wp_send_json_error();
758
759 $term = get_term( $term['term_id'], $taxonomy );
760
761 // error?
762 if ( is_wp_error( $term ) )
763 wp_send_json_error();
764 else {
765 wp_send_json_success(
766 [
767 'name' => $term->name,
768 'term_id' => $term->term_id,
769 'url' => admin_url( 'upload.php?mode=' . $this->mode . '&' . $taxonomy . '=' . $term->term_id ),
770 'select' => $this->get_folders( $taxonomy, $term->term_id )
771 ]
772 );
773 }
774 }
775
776 /**
777 * AJAX action to rename term.
778 *
779 * @return void
780 */
781 public function rename_term() {
782 // no data?
783 if ( ! isset( $_POST['term_id'], $_POST['name'], $_POST['nonce'] ) )
784 wp_send_json_error();
785
786 // invalid nonce?
787 if ( ! ctype_alnum( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'rl-folders-ajax-library-nonce' ) )
788 wp_send_json_error();
789
790 // sanitize term id
791 $term_id = (int) $_POST['term_id'];
792
793 if ( $term_id <= 0 )
794 wp_send_json_error();
795
796 // get taxonomy
797 $taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];
798
799 // update term, name is sanitized inside wp_update_term with sanitize_term function
800 $update = wp_update_term( $term_id, $taxonomy, [ 'name' => $_POST['name'] ] );
801
802 // error?
803 if ( is_wp_error( $update ) )
804 wp_send_json_error();
805
806 $term = get_term( $term_id, $taxonomy );
807
808 // error?
809 if ( is_wp_error( $term ) )
810 wp_send_json_error();
811 else {
812 wp_send_json_success(
813 [
814 'name' => $term->name,
815 'select' => $this->get_folders( $taxonomy, $term_id )
816 ]
817 );
818 }
819 }
820
821 /**
822 * AJAX action to assign new term to attachments.
823 *
824 * @return void
825 */
826 public function move_attachments() {
827 // no data?
828 if ( ! isset( $_POST['attachment_ids'], $_POST['old_term_id'], $_POST['new_term_id'], $_POST['nonce'] ) )
829 wp_send_json_error();
830
831 // invalid nonce?
832 if ( ! ctype_alnum( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'rl-folders-ajax-library-nonce' ) )
833 wp_send_json_error();
834
835 // not empty attachment ids array?
836 if ( empty( $_POST['attachment_ids'] ) || ! is_array( $_POST['attachment_ids'] ) )
837 wp_send_json_error();
838
839 // prepare data
840 $ids = $all_terms = [];
841 $attachments = [
842 'success' => [],
843 'failure' => [],
844 'duplicated' => []
845 ];
846
847 // filter unwanted data
848 $ids = array_unique( array_filter( array_map( 'intval', $_POST['attachment_ids'] ) ) );
849
850 // no ids?
851 if ( empty( $ids ) )
852 wp_send_json_error();
853
854 // prepare term ids
855 $old_term_id = (int) $_POST['old_term_id'];
856 $new_term_id = (int) $_POST['new_term_id'];
857
858 // get taxonomy
859 $taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];
860
861 // moving to root folder?
862 if ( $new_term_id === 0 ) {
863 foreach ( $ids as $id ) {
864 // get attachment term ids
865 $all_terms[$id] = wp_get_object_terms( $id, $taxonomy, [ 'fields' => 'ids' ] );
866
867 // remove all terms assigned to attachment
868 if ( ! is_wp_error( wp_set_object_terms( $id, null, $taxonomy, false ) ) )
869 $attachments['success'][] = $id;
870 else
871 $attachments['failure'][] = $id;
872 }
873 } else {
874 foreach ( $ids as $id ) {
875 // get attachment term ids
876 $terms = wp_get_object_terms( $id, $taxonomy, [ 'fields' => 'ids' ] );
877
878 // got terms?
879 if ( ! is_wp_error( $terms ) ) {
880 // save existing term (attachment already assigned to this term)
881 if ( in_array( $new_term_id, $terms, true ) )
882 $attachments['duplicated'][] = $id;
883
884 // update attachment's term
885 if ( ! is_wp_error( wp_set_object_terms( $id, $new_term_id, $taxonomy, false ) ) )
886 $attachments['success'][] = $id;
887 else
888 $attachments['failure'][] = $id;
889 }
890 }
891 }
892
893 if ( empty( $attachments['success'] ) )
894 wp_send_json_error();
895 else {
896 wp_send_json_success(
897 [
898 'attachments' => $attachments,
899 'terms' => $all_terms
900 ]
901 );
902 }
903 }
904
905 /**
906 * Change wp_list_categories HTML link.
907 *
908 * @param array $matches Matched elements
909 * @return string
910 */
911 public function replace_folders_href( $matches ) {
912 // get taxonomy
913 $taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];
914
915 // set 'all files' folder
916 $term_id = -1;
917 $url_term_id = 0;
918
919 // any matches?
920 if ( ! empty( $matches[1] ) ) {
921 $params = parse_url( html_entity_decode( urldecode( $matches[1] ) ) );
922
923 if ( isset( $params['query'] ) ) {
924 // parse query string
925 parse_str( $params['query'], $atts );
926
927 if ( isset( $atts['term'] ) ) {
928 // get term
929 $term = get_term_by( 'slug', $atts['term'], $taxonomy );
930
931 // valid term?
932 if ( $term !== false ) {
933 $this->term_counters['keys'][] = $term->term_id;
934
935 // set term id
936 $url_term_id = $term_id = $term->term_id;
937 }
938 }
939 }
940 }
941
942 // escape url early
943 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 . '"';
944 }
945
946 /**
947 * Change wp_list_categories HTML link by adding attachment counter.
948 *
949 * @param array $matches Matched elements
950 * @return string
951 */
952 public function replace_folders_count( $matches ) {
953 if ( isset( $matches[1] ) ) {
954 $count = (int) str_replace( [ ' ', '&nbsp;' ], '', $matches[1] );
955 $this->term_counters['values'][] = $count;
956
957 return ' (' . $count . ')</a>';
958 }
959
960 return '</a>';
961 }
962
963 /**
964 * Change wp_list_categories HTML output by adding jsTree attributes if needed.
965 *
966 * @param array $matches Matched elements
967 * @return string
968 */
969 public function open_folders( $matches ) {
970 if ( isset( $matches[0] ) ) {
971 // open parent term
972 if ( isset( $matches[0] ) && strpos( $matches[0], 'current-cat-ancestor' ) !== false )
973 return $matches[0] . ' data-jstree=\'{ "opened": true }\'';
974
975 // select current term
976 if ( strpos( $matches[0], 'current-cat' ) !== false )
977 return $matches[0] . ' data-jstree=\'{ "selected": true }\'';
978 }
979 }
980
981 /**
982 * Enqueue all needed scripts and styles for media library and modal screens.
983 *
984 * @global string $pagenow
985 * @global object $wp_list_table
986 * @global array $_wp_admin_css_colors
987 *
988 * @param string $page Current page similar to $pagenow depends on from which filter function was called
989 * @return void
990 */
991 public function add_library_scripts( $page ) {
992 // count how many times function was executed, allow this only once
993 static $run = 0;
994
995 // allow only wp media scripts (empty $page), upload.php or media-new.php
996 if ( ! ( ( $page === '' || $page === 'upload.php' || $page === 'media-new.php' ) && $run < 1 ) )
997 return;
998
999 global $pagenow;
1000
1001 $run++;
1002
1003 // change page for wp_enqueue_media
1004 if ( $page === '' ) {
1005 if ( $pagenow === 'upload.php' )
1006 $page = 'upload.php';
1007 else
1008 $page = 'media';
1009 }
1010
1011 // get main instance
1012 $rl = Responsive_Lightbox();
1013
1014 // include select2 styles
1015 wp_enqueue_style( 'responsive-lightbox-admin-select2', RESPONSIVE_LIGHTBOX_URL . '/assets/select2/select2' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.css', [], $rl->defaults['version'] );
1016
1017 // filterable media folders taxonomy
1018 $taxonomy = get_taxonomy( $rl->options['folders']['media_taxonomy'] );
1019
1020 // no taxonomy? it should be available here, updated in init_folders method
1021 if ( $taxonomy === false )
1022 return;
1023
1024 // main script dependencies
1025 $dependencies = [ 'jquery', 'underscore', 'jquery-ui-draggable', 'jquery-ui-droppable', 'media-models', 'tags-suggest' ];
1026
1027 // create folder counters
1028 $counters = [];
1029
1030 if ( $page !== 'media' ) {
1031 // prepare variables
1032 $no_items = '';
1033 $childless = false;
1034
1035 // include styles
1036 wp_enqueue_style( 'responsive-lightbox-folders-admin-css', RESPONSIVE_LIGHTBOX_URL . '/css/admin-folders.css' );
1037 wp_enqueue_style( 'responsive-lightbox-folders-perfect-scrollbar', RESPONSIVE_LIGHTBOX_URL . '/assets/perfect-scrollbar/perfect-scrollbar' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.css', [], '1.5.3' );
1038 wp_enqueue_style( 'responsive-lightbox-folders-jstree', RESPONSIVE_LIGHTBOX_URL . '/assets/jstree/themes/default/style' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.css', [], '3.3.17' );
1039
1040 // get color scheme global
1041 global $_wp_admin_css_colors;
1042
1043 // set default color;
1044 $color = '0,160,210';
1045
1046 if ( ! empty( $_wp_admin_css_colors ) ) {
1047 // get current admin color scheme name
1048 $current_color_scheme = get_user_option( 'admin_color' );
1049
1050 if ( empty( $current_color_scheme ) )
1051 $current_color_scheme = 'fresh';
1052
1053 // color exists? some schemes don't have 4 colors
1054 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] ) ) {
1055 // convert color
1056 $rgb = $rl->hex2rgb( $_wp_admin_css_colors[$current_color_scheme]->colors[3] );
1057
1058 // valid color?
1059 if ( $rgb !== false )
1060 $color = implode( ',', $rgb );
1061 }
1062 }
1063
1064 // $color is already validated, no escaping
1065 wp_add_inline_style(
1066 'responsive-lightbox-folders-jstree',
1067 '#rl-folders-tree-container .jstree .rl-folders-state-active.rl-folders-state-hover {
1068 background: #fff !important;
1069 }
1070 #rl-folders-tree-container .jstree-container-ul .jstree-wholerow-clicked,
1071 #rl-folders-tree-container .jstree-container-ul:not(.jstree-wholerow-ul) .jstree-clicked {
1072 background: rgba(' . esc_attr( $color ) . ', 0.15);
1073 }
1074 #rl-folders-tree-container .jstree-container-ul .jstree-wholerow-hovered,
1075 #rl-folders-tree-container .jstree-container-ul:not(.jstree-wholerow-ul) .jstree-hovered {
1076 background: rgba(' . esc_attr( $color ) . ', 0.05);
1077 }'
1078 );
1079
1080 // list categories parameters
1081 $categories = [
1082 'orderby' => 'name',
1083 'order' => 'asc',
1084 'show_count' => true,
1085 'show_option_all' => '',
1086 'show_option_none' => '',
1087 'use_desc_for_title' => false,
1088 'title_li' => '',
1089 'hide_empty' => false,
1090 'hierarchical' => true,
1091 'taxonomy' => $taxonomy->name,
1092 'hide_title_if_empty' => true,
1093 'echo' => false
1094 ];
1095
1096 // get current term id
1097 $term_id = isset( $_GET[$taxonomy->name] ) ? (int) $_GET[$taxonomy->name] : 0;
1098
1099 // list mode?
1100 if ( $this->mode === 'list' ) {
1101 // get global wp list table instance
1102 global $wp_list_table;
1103
1104 // empty instance?
1105 if ( is_null( $wp_list_table ) )
1106 $wp_list_table = _get_list_table( 'WP_Media_List_Table' );
1107
1108 // start buffering
1109 ob_start();
1110
1111 // display "no media" table row
1112 echo '<tr class="no-items"><td class="colspanchange" colspan="' . (int) $wp_list_table->get_column_count() . '">';
1113
1114 $wp_list_table->no_items();
1115
1116 echo '</td></tr>';
1117
1118 // save "no media" table row
1119 $no_items = ob_get_contents();
1120
1121 // clear the buffer
1122 ob_end_clean();
1123
1124 // valid term?
1125 if ( $term_id > 0 ) {
1126 $children = get_term_children( $term_id, $taxonomy->name );
1127
1128 // found any children?
1129 $childless = ! ( ! empty( $children ) && ! is_wp_error( $children ) );
1130 }
1131 }
1132
1133 // set current term id
1134 if ( $term_id > 0 )
1135 $categories['current_category'] = $term_id;
1136
1137 // hide filter for grid
1138 if ( $this->mode !== 'list' ) {
1139 wp_add_inline_style(
1140 'responsive-lightbox-folders-admin-css',
1141 '#media-attachment-rl-folders-filters { display: none; }
1142 .media-modal-content .media-frame select.attachment-filters {
1143 max-width: 100%;
1144 min-width: auto;
1145 }'
1146 );
1147 }
1148
1149 // get taxonomy html output
1150 $html = wp_list_categories( $categories );
1151
1152 if ( $html !== '' ) {
1153 // fix for urls
1154 $html = preg_replace_callback( '/href=(?:\'|")(.*?)(?:\'|")/', [ $this, 'replace_folders_href' ], $html );
1155
1156 // fix for counters
1157 $html = preg_replace_callback( '/<\/a> \(((?:\d+|&nbsp;)+)\)/', [ $this, 'replace_folders_count' ], $html );
1158
1159 // open all needed folders at start
1160 if ( $term_id > 0 )
1161 $html = preg_replace_callback( '/class="cat-item cat-item-(\d+)(?:[a-z\s0-9-]+)?"/', [ $this, 'open_folders' ], $html );
1162
1163 // check whether counters are valid
1164 if ( ! ( empty( $this->term_counters['keys'] ) || empty( $this->term_counters['values'] ) || count( $this->term_counters['keys'] ) !== count( $this->term_counters['values'] ) ) ) {
1165 //@TODO counters are supposed to be used in JS but not implemented yet
1166 // update folder counters
1167 $counters = array_combine( $this->term_counters['keys'], $this->term_counters['values'] );
1168 }
1169 }
1170
1171 // root folder query
1172 $root_query = new WP_Query(
1173 apply_filters(
1174 'rl_root_folder_query_args',
1175 [
1176 'rl_folders_root' => true,
1177 'posts_per_page' => -1,
1178 'post_type' => 'attachment',
1179 'post_status' => 'inherit,private',
1180 'fields' => 'ids',
1181 'no_found_rows' => false,
1182 'tax_query' => [
1183 [
1184 'relation' => 'AND',
1185 [
1186 'taxonomy' => $taxonomy->name,
1187 'field' => 'id',
1188 'terms' => 0,
1189 'include_children' => false,
1190 'operator' => 'NOT EXISTS'
1191 ]
1192 ]
1193 ]
1194 ]
1195 )
1196 );
1197
1198 // set number of all attachments
1199 $counters[-1] = (int) apply_filters( 'rl_count_attachments', 0 );
1200
1201 // set number of root attachments (not categorized)
1202 $counters[0] = (int) $root_query->post_count;
1203
1204 $html = '
1205 <ul>
1206 <li class="cat-item cat-item-all"' . ( $term_id === 0 ? ' data-jstree=\'{ "selected": true }\'' : '' ) . '>
1207 <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>
1208 </li>
1209 <li class="cat-item cat-item-0" data-jstree=\'{ "opened": true' . ( $term_id === -1 ? ', "selected": true ' : '' ) . ' }\'>
1210 <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>
1211 <ul>' . $html . '</ul>
1212 </li>
1213 </ul>';
1214
1215 // register scripts
1216 wp_register_script( 'responsive-lightbox-folders-jstree', RESPONSIVE_LIGHTBOX_URL . '/assets/jstree/jstree' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', [], '3.3.17', false );
1217 wp_register_script( 'responsive-lightbox-folders-perfect-scrollbar', RESPONSIVE_LIGHTBOX_URL . '/assets/perfect-scrollbar/perfect-scrollbar' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', [], '1.5.3', false );
1218
1219 $dependencies[] = 'responsive-lightbox-folders-jstree';
1220 $dependencies[] = 'responsive-lightbox-folders-perfect-scrollbar';
1221 }
1222
1223 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 );
1224
1225 wp_enqueue_script( 'responsive-lightbox-folders-admin', RESPONSIVE_LIGHTBOX_URL . '/js/admin-folders.js', $dependencies, $rl->defaults['version'], false );
1226
1227 if ( $page === 'media' ) {
1228 // prepare script data
1229 $script_data = [
1230 'taxonomy' => $taxonomy->name,
1231 'page' => $page,
1232 'root' => esc_html__( 'Root Folder', 'responsive-lightbox' ),
1233 'terms' => wp_dropdown_categories(
1234 [
1235 'orderby' => 'name',
1236 'order' => 'asc',
1237 'show_option_all' => esc_html__( 'All Files', 'responsive-lightbox' ),
1238 'show_count' => false,
1239 'hide_empty' => false,
1240 'hierarchical' => true,
1241 'selected' => ( isset( $_GET[$taxonomy->name] ) ? (int) $_GET[$taxonomy->name] : 0 ),
1242 'name' => $taxonomy->name,
1243 'taxonomy' => $taxonomy->name,
1244 'hide_if_empty' => true,
1245 'echo' => false
1246 ]
1247 )
1248 ];
1249 } else {
1250 // prepare script data
1251 $script_data = [
1252 'remove_children' => $rl->options['folders']['folders_removal'],
1253 'wholerow' => $rl->options['folders']['jstree_wholerow'],
1254 'theme' => 'default',
1255 'counters' => $counters,
1256 'no_media_items' => $no_items,
1257 'taxonomy' => $taxonomy->name,
1258 'page' => $page,
1259 'root' => esc_html__( 'Root Folder', 'responsive-lightbox' ),
1260 'all_terms' => esc_html__( 'All Files', 'responsive-lightbox' ),
1261 'new_folder' => esc_html__( 'New Folder', 'responsive-lightbox' ),
1262 'delete_term' => esc_html__( 'Are you sure you want to delete this folder?', 'responsive-lightbox' ),
1263 'delete_terms' => esc_html__( 'Are you sure you want to delete this folder with all subfolders?', 'responsive-lightbox' ),
1264 'nonce' => wp_create_nonce( 'rl-folders-ajax-library-nonce' ),
1265 'terms' => wp_dropdown_categories(
1266 [
1267 'orderby' => 'name',
1268 'order' => 'asc',
1269 'show_option_all' => esc_html__( 'All Files', 'responsive-lightbox' ),
1270 'show_count' => false,
1271 'hide_empty' => false,
1272 'hierarchical' => true,
1273 'selected' => ( isset( $_GET[$taxonomy->name] ) ? (int) $_GET[$taxonomy->name] : 0 ),
1274 'name' => $taxonomy->name,
1275 'taxonomy' => $taxonomy->name,
1276 'hide_if_empty' => true,
1277 'echo' => false
1278 ]
1279 ),
1280 'template' => '
1281 <div id="rl-folders-tree-container">
1282 <div class="media-toolbar wp-filter">
1283 <div class="view-switch rl-folders-action-links">
1284 <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>
1285 <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>
1286 <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>
1287 <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>
1288 <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>
1289 <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>
1290 <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>
1291 <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>
1292 <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>
1293 </div>
1294 </div>
1295 <div id="rl-folders-tree">' . wp_kses_post( $html ) . '</div>
1296 </div>'
1297 ];
1298 }
1299
1300 wp_add_inline_script( 'responsive-lightbox-folders-admin', 'var rlFoldersArgs = ' . wp_json_encode( $script_data ) . ";\n", 'before' );
1301
1302 add_action( 'admin_print_styles', [ $this, 'admin_print_media_styles' ] );
1303 }
1304
1305 /**
1306 * CSS fix for media folders checklist.
1307 *
1308 * @return void
1309 */
1310 public function admin_print_media_styles() {
1311 echo '<style>.rl_media_folder li .selectit input[type="checkbox"] { margin: 0 3px; }</style>';
1312 }
1313
1314 /**
1315 * Count attachments.
1316 *
1317 * @return int
1318 */
1319 public function count_attachments() {
1320 $count = wp_count_posts( 'attachment' );
1321
1322 return (int) $count->inherit;
1323 }
1324
1325 /**
1326 * Get all previously used media taxonomies.
1327 *
1328 * @global object $wpdb
1329 *
1330 * @return array
1331 */
1332 public function get_taxonomies() {
1333 global $wpdb;
1334
1335 // query
1336 $fields = $wpdb->get_col( "
1337 SELECT DISTINCT tt.taxonomy
1338 FROM " . $wpdb->prefix . "term_taxonomy tt
1339 LEFT JOIN " . $wpdb->prefix . "term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
1340 LEFT JOIN " . $wpdb->prefix . "posts p ON p.ID = tr.object_id
1341 WHERE p.post_type = 'attachment'
1342 ORDER BY tt.taxonomy ASC"
1343 );
1344
1345 if ( ! empty( $fields ) ) {
1346 // remove polylang taxonomy
1347 if ( ( $key = array_search( 'language', $fields, true ) ) !== false )
1348 unset( $fields[$key] );
1349 }
1350
1351 return $fields;
1352 }
1353 }
1354