PluginProbe ʕ •ᴥ•ʔ
Responsive Lightbox & Gallery / trunk
Responsive Lightbox & Gallery vtrunk
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 / settings / class-settings-folders.php
responsive-lightbox / includes / settings Last commit date
class-settings-addons.php 4 months ago class-settings-base.php 5 months ago class-settings-builder.php 5 months ago class-settings-capabilities.php 5 months ago class-settings-folders.php 4 months ago class-settings-galleries.php 5 months ago class-settings-general.php 5 months ago class-settings-licenses.php 4 months ago class-settings-lightboxes.php 4 months ago class-settings-remote-library.php 5 months ago
class-settings-folders.php
358 lines
1 <?php
2 /**
3 * Responsive Lightbox Folders Settings
4 *
5 * @package Responsive_Lightbox
6 */
7
8 // exit if accessed directly
9 if ( ! defined( 'ABSPATH' ) )
10 exit;
11
12 /**
13 * Responsive Lightbox Folders Settings class.
14 *
15 * @class Responsive_Lightbox_Settings_Folders
16 */
17 class Responsive_Lightbox_Settings_Folders extends Responsive_Lightbox_Settings_Base {
18
19 /**
20 * Tab key identifier.
21 *
22 * @var string
23 */
24 const TAB_KEY = 'folders';
25
26 /**
27 * Class constructor.
28 *
29 * @return void
30 */
31 public function __construct() {
32 parent::__construct();
33
34 // allow to load old taxonomies from settings page
35 add_action( 'wp_ajax_rl-folders-load-old-taxonomies', [ $this, 'load_old_taxonomies' ] );
36 }
37
38 /**
39 * Validate settings for Folders tab.
40 *
41 * Handles field sanitization for folder settings.
42 *
43 * @param array $input Input data from form submission.
44 * @return array Validated data.
45 */
46 public function validate( $input ) {
47 // check if this is a reset operation
48 if ( $this->is_reset_request() ) {
49 $input = $this->merge_with_defaults( [] );
50 add_settings_error( 'reset_rl_folders', 'settings_restored', esc_html__( 'Settings restored to defaults.', 'responsive-lightbox' ), 'updated' );
51 return $input;
52 }
53
54 // sanitize all fields
55 $input = $this->sanitize_fields( $input, 'folders' );
56
57 // validate folders_source against filtered options
58 $allowed_sources = array_keys( apply_filters( 'rl_folders_source_options', [
59 'rl_media_folder' => __( 'RLG Folder (recommended)', 'responsive-lightbox' ),
60 'custom_taxonomy' => __( 'Custom Taxonomy', 'responsive-lightbox' )
61 ] ) );
62
63 if ( ! in_array( $input['folders_source'], $allowed_sources, true ) ) {
64 $input['folders_source'] = 'rl_media_folder';
65 }
66
67 // validate media_taxonomy only when using custom_taxonomy mode
68 if ( $input['folders_source'] === 'custom_taxonomy' ) {
69 // check if media_taxonomy is empty or invalid
70 if ( empty( $input['media_taxonomy'] ) || $input['media_taxonomy'] === 'rl_media_folder' ) {
71 $input['folders_source'] = 'rl_media_folder';
72 add_settings_error( 'media_taxonomy', 'media_taxonomy_fallback', esc_html__( 'Media Folders selection is required when using Custom Taxonomy. Reverted to RLG Folder.', 'responsive-lightbox' ), 'error' );
73 } else {
74 // validate against DB taxonomies + registered hierarchical attachment taxonomies
75 $db_taxonomies = $this->get_taxonomies();
76 $db_taxonomies = is_array( $db_taxonomies ) ? $db_taxonomies : [];
77
78 $registered_taxonomies = get_taxonomies(
79 [
80 'object_type' => [ 'attachment' ],
81 'hierarchical' => true,
82 '_builtin' => false
83 ],
84 'names',
85 'and'
86 );
87 $registered_taxonomies = is_array( $registered_taxonomies ) ? $registered_taxonomies : [];
88
89 $available_taxonomies = array_values( array_unique( array_merge( $db_taxonomies, $registered_taxonomies ) ) );
90 $available_taxonomies = array_values( array_diff( $available_taxonomies, [ 'rl_media_folder', 'rl_media_tag', 'language' ] ) );
91 $available_taxonomies = array_map( 'sanitize_key', $available_taxonomies );
92
93 if ( ! in_array( $input['media_taxonomy'], $available_taxonomies, true ) ) {
94 $input['folders_source'] = 'rl_media_folder';
95 add_settings_error( 'media_taxonomy', 'media_taxonomy_invalid', esc_html__( 'Selected taxonomy does not exist. Reverted to RLG Folder.', 'responsive-lightbox' ), 'error' );
96 }
97 }
98 }
99
100 // enforce RLG-only features when using custom taxonomy
101 if ( $input['folders_source'] === 'custom_taxonomy' ) {
102 $input['media_tags'] = false;
103 $input['show_in_menu'] = false;
104 $input['folders_removal'] = false;
105 $input['jstree_wholerow'] = false;
106 }
107
108 return $input;
109 }
110
111 /**
112 * Provide settings data for this tab.
113 *
114 * @param array $data Settings data.
115 * @return array
116 */
117 public function settings_data( $data ) {
118 // get main instance
119 $rl = Responsive_Lightbox();
120
121 $data[self::TAB_KEY] = [
122 'option_name' => 'responsive_lightbox_folders',
123 'option_group' => 'responsive_lightbox_folders',
124 'validate' => [ $this, 'validate' ],
125 'sections' => [
126 'responsive_lightbox_folders' => [
127 'title' => __( 'Folders Settings', 'responsive-lightbox' ),
128 'description' => '',
129 'fields' => [
130 'active' => [
131 'title' => __( 'Folders', 'responsive-lightbox' ),
132 'type' => 'boolean',
133 'label' => __( 'Enable media folders.', 'responsive-lightbox' )
134 ],
135 'folders_source' => [
136 'title' => __( 'Folders Source', 'responsive-lightbox' ),
137 'type' => 'radio',
138 'description' => __( 'Select the source for organizing media and Media Folder galleries.', 'responsive-lightbox' ) . ' ' . __( 'If you have ever used categories or custom taxonomies for media library you may try to <a id="rl-folders-load-old-taxonomies" href="#">load and use them.</a>', 'responsive-lightbox' ),
139 'options' => apply_filters( 'rl_folders_source_options', [
140 'rl_media_folder' => __( 'RLG Folder (recommended)', 'responsive-lightbox' ),
141 'custom_taxonomy' => __( 'Custom Taxonomy', 'responsive-lightbox' )
142 ] )
143 ],
144 'media_taxonomy' => [
145 'title' => '',
146 'type' => 'select',
147 'description' => __( 'Select the data source media folders.', 'responsive-lightbox' ),
148 'after_field' => '<span class="spinner rl-spinner"></span>',
149 'options' => [],
150 'logic' => [
151 'field' => 'folders_source',
152 'operator' => 'is',
153 'value' => 'custom_taxonomy',
154 'action' => 'show',
155 ],
156 'animation' => 'slide'
157 ],
158 'media_ui' => [
159 'title' => __( 'Media Library UI', 'responsive-lightbox' ),
160 'type' => 'boolean',
161 'label' => __( 'Enable Media Library folders UI.', 'responsive-lightbox' ),
162 'description' => __( 'Disable to keep taxonomy available for galleries without adding Media Library UI.', 'responsive-lightbox' )
163 ],
164 'media_tags' => [
165 'title' => __( 'Media Tags', 'responsive-lightbox' ),
166 'type' => 'boolean',
167 'label' => __( 'Enable media tags.', 'responsive-lightbox' ),
168 'description' => __( 'Enable if you want to use media tags.', 'responsive-lightbox' ),
169 'logic' => [
170 'field' => 'media_ui',
171 'operator' => 'isnot',
172 'value' => 'true',
173 'action' => 'disable',
174 ]
175 ],
176 'show_in_menu' => [
177 'title' => __( 'Show in Menu', 'responsive-lightbox' ),
178 'type' => 'boolean',
179 'label' => __( 'Enable to show the taxonomy in the admin menu.', 'responsive-lightbox' ),
180 'logic' => [
181 'field' => 'media_ui',
182 'operator' => 'isnot',
183 'value' => 'true',
184 'action' => 'disable',
185 ]
186 ],
187 'folders_removal' => [
188 'title' => __( 'Subfolder Removal', 'responsive-lightbox' ),
189 'type' => 'boolean',
190 'label' => __( 'Select to remove subfolders when parent folder is deleted.', 'responsive-lightbox' ),
191 'logic' => [
192 'field' => 'media_ui',
193 'operator' => 'isnot',
194 'value' => 'true',
195 'action' => 'disable',
196 ]
197 ],
198 'jstree_wholerow' => [
199 'title' => __( 'Whole Row', 'responsive-lightbox' ),
200 'type' => 'boolean',
201 'label' => __( 'Enable to highlight folder\'s row as a clickable area.', 'responsive-lightbox' ),
202 'logic' => [
203 'field' => 'media_ui',
204 'operator' => 'isnot',
205 'value' => 'true',
206 'action' => 'disable',
207 ]
208 ]
209 ]
210 ]
211 ]
212 ];
213
214 return $data;
215 }
216
217 /**
218 * Load previously used media taxonomies via AJAX.
219 *
220 * @return void
221 */
222 public function load_old_taxonomies() {
223 // check capability
224 if ( ! current_user_can( 'manage_options' ) )
225 wp_send_json_error( [ 'message' => __( 'You do not have permission to perform this action.', 'responsive-lightbox' ) ] );
226
227 // no data?
228 if ( ! isset( $_POST['taxonomies'], $_POST['nonce'] ) )
229 wp_send_json_error( [ 'message' => __( 'Missing required data.', 'responsive-lightbox' ) ] );
230
231 // invalid taxonomies format?
232 if ( ! is_array( $_POST['taxonomies'] ) )
233 wp_send_json_error( [ 'message' => __( 'Invalid data format.', 'responsive-lightbox' ) ] );
234
235 // invalid nonce?
236 if ( ! wp_verify_nonce( $_POST['nonce'], 'rl-folders-ajax-taxonomies-nonce' ) )
237 wp_send_json_error( [ 'message' => __( 'Security check failed. Please refresh the page and try again.', 'responsive-lightbox' ) ] );
238
239 // validate taxonomies are strings
240 $taxonomies_input = array_filter( $_POST['taxonomies'], 'is_string' );
241 $taxonomies_input = array_map( 'sanitize_key', $taxonomies_input );
242
243 // get taxonomies used by attachments (DB) and currently registered
244 $db_taxonomies = $this->get_taxonomies();
245 $db_taxonomies = is_array( $db_taxonomies ) ? $db_taxonomies : [];
246
247 $registered_taxonomies = get_taxonomies(
248 [
249 'object_type' => [ 'attachment' ],
250 'hierarchical' => true,
251 '_builtin' => false
252 ],
253 'names',
254 'and'
255 );
256 $registered_taxonomies = is_array( $registered_taxonomies ) ? $registered_taxonomies : [];
257
258 // combine DB-discovered and currently registered taxonomies
259 $fields = array_values( array_unique( array_merge( $db_taxonomies, $registered_taxonomies ) ) );
260
261 // any results?
262 if ( ! empty( $fields ) ) {
263 // remove main taxonomy
264 if ( ( $key = array_search( 'rl_media_folder', $fields, true ) ) !== false )
265 unset( $fields[$key] );
266
267 // remove media tags
268 if ( ( $key = array_search( 'rl_media_tag', $fields, true ) ) !== false )
269 unset( $fields[$key] );
270
271 // remove polylang taxonomy if present
272 if ( ( $key = array_search( 'language', $fields, true ) ) !== false )
273 unset( $fields[$key] );
274
275 // sanitize and normalize
276 $fields = array_map( 'sanitize_key', $fields );
277 $fields = array_filter( $fields, 'is_string' );
278 $fields = array_values( array_unique( $fields ) );
279 }
280
281 // save discovered taxonomies to options (merge with existing, preserve on scan failure)
282 $options = get_option( 'responsive_lightbox_folders', [] );
283 $options = is_array( $options ) ? $options : [];
284 $existing = isset( $options['custom_taxonomies'] ) && is_array( $options['custom_taxonomies'] ) ? $options['custom_taxonomies'] : [];
285
286 if ( ! empty( $fields ) ) {
287 $options['custom_taxonomies'] = array_values( array_unique( array_merge( $existing, $fields ) ) );
288 update_option( 'responsive_lightbox_folders', $options );
289 }
290 // Note: We don't clear custom_taxonomies when scan returns nothing to avoid
291 // wiping stored taxonomies on transient DB failures or when no new taxonomies exist
292
293 // send taxonomies with counts and message
294 $count = count( $fields );
295 $new_taxonomies = array_values( array_diff( $fields, $taxonomies_input ) );
296 $count_new = count( $new_taxonomies );
297
298 if ( $count > 0 ) {
299 if ( $count_new > 0 ) {
300 $message = sprintf(
301 /* translators: 1: total taxonomies, 2: newly added taxonomies */
302 __( '%1$d custom taxonomies available. %2$d new added to the list.', 'responsive-lightbox' ),
303 $count,
304 $count_new
305 );
306 } else {
307 $message = sprintf(
308 _n(
309 '%d custom taxonomy available (registered or previously loaded). No new taxonomies were added.',
310 '%d custom taxonomies available (registered or previously loaded). No new taxonomies were added.',
311 $count,
312 'responsive-lightbox'
313 ),
314 $count
315 );
316 }
317 } else {
318 $message = __( 'No custom taxonomies found.', 'responsive-lightbox' );
319 }
320
321 wp_send_json_success( [
322 'taxonomies' => array_values( $fields ),
323 'count' => $count,
324 'count_new' => $count_new,
325 'message' => $message
326 ] );
327 }
328
329 /**
330 * Get all previously used media taxonomies.
331 *
332 * @global object $wpdb
333 *
334 * @return array
335 */
336 private function get_taxonomies() {
337 global $wpdb;
338
339 // query
340 $fields = $wpdb->get_col( "
341 SELECT DISTINCT tt.taxonomy
342 FROM " . $wpdb->prefix . "term_taxonomy tt
343 LEFT JOIN " . $wpdb->prefix . "term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
344 LEFT JOIN " . $wpdb->prefix . "posts p ON p.ID = tr.object_id
345 WHERE p.post_type = 'attachment'
346 ORDER BY tt.taxonomy ASC"
347 );
348
349 if ( ! empty( $fields ) ) {
350 // remove polylang taxonomy
351 if ( ( $key = array_search( 'language', $fields, true ) ) !== false )
352 unset( $fields[$key] );
353 }
354
355 return $fields;
356 }
357 }
358