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