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 / class-settings.php
responsive-lightbox / includes Last commit date
galleries 1 week ago providers 4 months ago settings 4 months ago class-fast-image.php 2 years ago class-folders.php 1 week ago class-frontend.php 1 week ago class-galleries.php 4 months ago class-multilang.php 2 years ago class-remote-library-api.php 1 week ago class-remote-library.php 1 week ago class-settings-api.php 1 month ago class-settings-data.php 5 months ago class-settings-pages.php 4 months ago class-settings.php 4 months ago class-tour.php 5 months ago class-welcome.php 4 months ago class-widgets.php 2 years ago functions.php 3 years ago
class-settings.php
720 lines
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 // include Settings API
7 include_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'class-settings-api.php' );
8 include_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'class-settings-pages.php' );
9
10 // include settings base class
11 include_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR . 'class-settings-base.php' );
12
13 // include settings page classes
14 include_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR . 'class-settings-general.php' );
15 include_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR . 'class-settings-builder.php' );
16 include_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR . 'class-settings-folders.php' );
17 include_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR . 'class-settings-remote-library.php' );
18 include_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR . 'class-settings-capabilities.php' );
19 include_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR . 'class-settings-galleries.php' );
20 include_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR . 'class-settings-licenses.php' );
21 include_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR . 'class-settings-addons.php' );
22 include_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR . 'class-settings-lightboxes.php' );
23
24 new Responsive_Lightbox_Settings();
25
26 /**
27 * Responsive Lightbox settings class.
28 *
29 * @class Responsive_Lightbox_Settings
30 */
31 class Responsive_Lightbox_Settings {
32
33 public $settings = [];
34 public $tabs = [];
35 public $scripts = [];
36 public $image_titles = [];
37
38 /**
39 * Cached feature flag for Settings API mode.
40 *
41 * @var bool|null
42 */
43 private $use_api_mode = null;
44
45 /**
46 * Class constructor.
47 *
48 * @return void
49 */
50 public function __construct() {
51 // set instance
52 $rl = Responsive_Lightbox();
53 $rl->settings = $this;
54
55 // initialize Settings API
56 $rl->settings_api = new Responsive_Lightbox_Settings_API( [
57 'prefix' => 'rl',
58 'domain' => 'responsive-lightbox',
59 'plugin' => 'Responsive Lightbox & Gallery',
60 'plugin_url' => RESPONSIVE_LIGHTBOX_URL,
61 'object' => $rl,
62 ] );
63
64 // initialize Settings API pages definition
65 new Responsive_Lightbox_Settings_Pages();
66
67 // initialize migrated settings pages
68 new Responsive_Lightbox_Settings_General();
69 new Responsive_Lightbox_Settings_Builder();
70 new Responsive_Lightbox_Settings_Folders();
71 new Responsive_Lightbox_Settings_Remote_Library();
72 new Responsive_Lightbox_Settings_Capabilities();
73 new Responsive_Lightbox_Settings_Galleries();
74 new Responsive_Lightbox_Settings_Licenses();
75 new Responsive_Lightbox_Settings_Addons();
76 new Responsive_Lightbox_Settings_Lightboxes();
77
78 // actions
79 add_action( 'after_setup_theme', [ $this, 'load_defaults' ] );
80 add_action( 'admin_init', [ $this, 'init_builder' ] );
81 add_action( 'admin_menu', [ $this, 'admin_menu_options' ], 12 );
82 add_action( 'rl_settings_sidebar', [ $this, 'settings_sidebar' ], 10, 5 );
83 add_filter( 'parent_file', [ $this, 'highlight_parent_menu' ] );
84 add_filter( 'submenu_file', [ $this, 'highlight_submenu' ], 10, 2 );
85
86 // legacy add-on bridge: convert $this->settings arrays to Settings API format
87 add_filter( 'rl_settings_data', [ $this, 'bridge_legacy_settings' ], 5 );
88 }
89
90 /**
91 * Render settings sidebar (legacy credits block).
92 *
93 * @param string $setting Setting group name.
94 * @param string $page_type Page type.
95 * @param string $url_page Current page URL slug.
96 * @param string $tab_key Current tab key.
97 * @param string $section_key Current section key.
98 * @return void
99 */
100 public function settings_sidebar( $setting, $page_type, $url_page, $tab_key, $section_key ) {
101 $rl = Responsive_Lightbox();
102
103 echo '
104 <div class="df-credits">
105 <h3 class="hndle">' . esc_html__( 'Responsive Lightbox & Gallery', 'responsive-lightbox' ) . ' ' . esc_html( $rl->defaults['version'] ) . '</h3>
106 <div class="inside">
107 <h4 class="inner">' . esc_html__( 'Need support?', 'responsive-lightbox' ) . '</h4>
108 <p class="inner">' . sprintf( esc_html__( 'If you are having problems with this plugin, please browse it\'s %s or talk about them in the %s.', 'responsive-lightbox' ), '<a href="http://www.dfactory.co/docs/responsive-lightbox/?utm_source=responsive-lightbox-settings&utm_medium=link&utm_campaign=docs" target="_blank">' . esc_html__( 'Documentation', 'responsive-lightbox' ) . '</a>', '<a href="http://www.dfactory.co/support/?utm_source=responsive-lightbox-settings&utm_medium=link&utm_campaign=support" target="_blank">' . esc_html__( 'Support forum', 'responsive-lightbox' ) . '</a>' ) . '</p>
109 <hr />
110 <h4 class="inner">' . esc_html__( 'Do you like this plugin?', 'responsive-lightbox' ) . '</h4>
111 <p class="inner">' . sprintf( esc_html__( '%s on WordPress.org', 'responsive-lightbox' ), '<a href="https://wordpress.org/support/plugin/responsive-lightbox/reviews/?filter=5" target="_blank">' . esc_html__( 'Rate it 5', 'responsive-lightbox' ) . '</a>' ) . '<br />' .
112 sprintf( esc_html__( 'Blog about it & link to the %s.', 'responsive-lightbox' ), '<a href="http://www.dfactory.co/products/responsive-lightbox/?utm_source=responsive-lightbox-settings&utm_medium=link&utm_campaign=blog-about" target="_blank">' . esc_html__( 'plugin page', 'responsive-lightbox' ) . '</a>' ) . '<br />' .
113 sprintf( esc_html__( 'Check out our other %s.', 'responsive-lightbox' ), '<a href="http://www.dfactory.co/products/?utm_source=responsive-lightbox-settings&utm_medium=link&utm_campaign=other-plugins" target="_blank">' . esc_html__( 'WordPress plugins', 'responsive-lightbox' ) . '</a>' ) . '
114 </p>
115 <hr />
116 <p class="df-link inner"><a href="http://www.dfactory.co/?utm_source=responsive-lightbox-settings&utm_medium=link&utm_campaign=created-by" target="_blank" title="Digital Factory"><img src="//rlg-53eb.kxcdn.com/df-black-sm.png" alt="Digital Factory" /></a></p>
117 </div>
118 </div>';
119 }
120
121 /**
122 * Get class data.
123 *
124 * @param string $attr
125 * @return mixed
126 */
127 public function get_data( $attr ) {
128 // Route to appropriate data source for migrated properties
129 if ( $attr === 'scripts' ) {
130 return Responsive_Lightbox_Settings_Data::get_scripts();
131 } elseif ( $attr === 'image_titles' ) {
132 return Responsive_Lightbox_Settings_Data::get_image_titles();
133 }
134
135 return property_exists( $this, $attr ) ? $this->{$attr} : null;
136 }
137
138 /**
139 * Get Settings API mode flag (centralized, cached).
140 *
141 * @return bool True if Settings API should handle menus/rendering, false for legacy mode.
142 */
143 public function get_use_api_mode() {
144 if ( $this->use_api_mode === null ) {
145 $this->use_api_mode = apply_filters( 'rl_use_settings_api_menus', true );
146 }
147 return $this->use_api_mode;
148 }
149
150 /**
151 * Get setting field definition from legacy settings array.
152 *
153 * Provides safe accessor with deprecation notice for direct array access.
154 *
155 * @since 2.6.1
156 * @param string $tab Tab/section key (e.g., 'settings', 'basicgrid_gallery')
157 * @param string $field Field key
158 * @return array|null Field definition array or null if not found
159 */
160 public function get_setting_field( $tab, $field ) {
161 _doing_it_wrong(
162 'Direct access to Responsive_Lightbox()->settings->settings[]',
163 'Use Responsive_Lightbox()->settings->get_setting_field() instead. Direct array access will be deprecated in a future version.',
164 '2.6.1'
165 );
166
167 // Get all fields for tab (uses Settings API first, then legacy fallback)
168 $fields = $this->get_setting_fields( $tab );
169
170 if ( isset( $fields[$field] ) ) {
171 return $fields[$field];
172 }
173
174 return null;
175 }
176
177 /**
178 * Get all fields for a settings tab.
179 *
180 * @since 2.6.1
181 * @param string $tab Tab/section key
182 * @return array Fields array or empty array if not found
183 */
184 public function get_setting_fields( $tab ) {
185 // Try Settings API first
186 $settings_data = apply_filters( 'rl_settings_data', [] );
187
188 if ( isset( $settings_data[$tab] ) ) {
189 $fields = [];
190
191 // Extract from top-level fields
192 if ( ! empty( $settings_data[$tab]['fields'] ) && is_array( $settings_data[$tab]['fields'] ) ) {
193 $fields = $settings_data[$tab]['fields'];
194 }
195
196 // Extract from nested sections
197 if ( ! empty( $settings_data[$tab]['sections'] ) && is_array( $settings_data[$tab]['sections'] ) ) {
198 foreach ( $settings_data[$tab]['sections'] as $section ) {
199 if ( ! empty( $section['fields'] ) && is_array( $section['fields'] ) ) {
200 $fields = array_merge( $fields, $section['fields'] );
201 }
202 }
203 }
204
205 if ( ! empty( $fields ) ) {
206 return $fields;
207 }
208 }
209
210 // Fallback to legacy $this->settings (for add-ons)
211 if ( isset( $this->settings[ $tab ]['fields'] ) ) {
212 return $this->settings[ $tab ]['fields'];
213 }
214
215 return [];
216 }
217
218
219 /**
220 * Get script option from scripts array.
221 *
222 * @since 2.6.1
223 * @param string $script Script key (e.g., 'swipebox', 'prettyphoto')
224 * @param string $option Option key (e.g., 'animations', 'themes')
225 * @return mixed Option value or null if not found
226 */
227 public function get_script_option( $script, $option ) {
228 _doing_it_wrong(
229 'Direct access to Responsive_Lightbox()->settings->scripts[]',
230 'Use Responsive_Lightbox()->settings->get_script_option() instead. Direct array access will be deprecated in a future version.',
231 '2.6.1'
232 );
233
234 $scripts = Responsive_Lightbox_Settings_Data::get_scripts();
235
236 if ( isset( $scripts[ $script ][ $option ] ) ) {
237 return $scripts[ $script ][ $option ];
238 }
239
240 return null;
241 }
242
243 /**
244 * Get all scripts array.
245 *
246 * @since 2.6.1
247 * @return array Scripts array
248 */
249 public function get_scripts() {
250 _doing_it_wrong(
251 'Direct access to Responsive_Lightbox()->settings->scripts',
252 'Use Responsive_Lightbox()->settings->get_scripts() instead. Direct array access will be deprecated in a future version.',
253 '2.6.1'
254 );
255
256 return Responsive_Lightbox_Settings_Data::get_scripts();
257 }
258
259 /**
260 * Get image titles array.
261 *
262 * @since 2.6.1
263 * @return array Image titles array
264 */
265 public function get_image_titles() {
266 _doing_it_wrong(
267 'Direct access to Responsive_Lightbox()->settings->image_titles',
268 'Use Responsive_Lightbox()->settings->get_image_titles() instead. Direct array access will be deprecated in a future version.',
269 '2.6.1'
270 );
271
272 return Responsive_Lightbox_Settings_Data::get_image_titles();
273 }
274
275 /**
276 * Check if a settings tab exists.
277 *
278 * @since 2.6.1
279 * @param string $tab Tab key
280 * @return bool True if tab exists, false otherwise
281 */
282 public function has_setting_tab( $tab ) {
283 if ( $tab === '' )
284 return false;
285
286 static $resolving = false;
287 if ( $resolving )
288 return isset( $this->settings[ $tab ] );
289
290 $resolving = true;
291 $settings_data = apply_filters( 'rl_settings_data', [] );
292 $resolving = false;
293 if ( isset( $settings_data[ $tab ] ) )
294 return true;
295
296 return isset( $this->settings[ $tab ] );
297 }
298
299 /**
300 * Get settings key by option_name lookup.
301 *
302 * Used to reverse-map from WordPress option_page to internal settings key.
303 *
304 * @since 2.6.1
305 * @param string $option_name Option name to search for (e.g., 'responsive_lightbox_settings')
306 * @return string|null Settings key or null if not found
307 */
308 public function get_settings_key_by_option( $option_name ) {
309 if ( $option_name === '' )
310 return '';
311
312 static $resolving = false;
313 if ( $resolving ) {
314 foreach ( $this->settings as $id => $setting ) {
315 if ( isset( $setting['option_group'] ) && $setting['option_group'] === $option_name )
316 return $id;
317
318 if ( isset( $setting['option_name'] ) && $setting['option_name'] === $option_name )
319 return $id;
320 }
321
322 return '';
323 }
324
325 // resolve from Settings API data first
326 $resolving = true;
327 $settings_data = apply_filters( 'rl_settings_data', [] );
328 $resolving = false;
329 if ( is_array( $settings_data ) ) {
330 foreach ( $settings_data as $id => $setting ) {
331 if ( isset( $setting['option_group'] ) && $setting['option_group'] === $option_name )
332 return $id;
333
334 if ( isset( $setting['option_name'] ) && $setting['option_name'] === $option_name )
335 return $id;
336 }
337 }
338
339 // fallback: legacy settings array
340 foreach ( $this->settings as $id => $setting ) {
341 if ( isset( $setting['option_group'] ) && $setting['option_group'] === $option_name )
342 return $id;
343
344 if ( isset( $setting['option_name'] ) && $setting['option_name'] === $option_name )
345 return $id;
346 }
347
348 return '';
349 }
350
351 /**
352 * Get full setting definition (not just fields).
353 *
354 * Used when needing option_name, option_group, or other metadata.
355 *
356 * @since 2.6.1
357 * @param string $tab Tab key
358 * @return array|null Full setting definition or null if not found
359 */
360 public function get_setting_definition( $tab ) {
361 if ( $tab === '' )
362 return null;
363
364 static $resolving = false;
365 if ( $resolving )
366 return isset( $this->settings[ $tab ] ) ? $this->settings[ $tab ] : null;
367
368 $resolving = true;
369 $settings_data = apply_filters( 'rl_settings_data', [] );
370 $resolving = false;
371 if ( isset( $settings_data[ $tab ] ) )
372 return $settings_data[ $tab ];
373
374 // Note: Accesses legacy structure directly; needed for metadata like option_name/option_group
375 // that isn't part of the fields array
376 if ( isset( $this->settings[ $tab ] ) )
377 return $this->settings[ $tab ];
378
379 return null;
380 }
381
382 /**
383 * Initialize additional stuff for builder.
384 *
385 * @return void
386 */
387 public function init_builder() {
388 // get main instance
389 $rl = Responsive_Lightbox();
390
391 // Category options now populated by Settings API (class-settings-builder.php)
392 // Legacy code removed - no longer writing to $this->settings
393
394 // flush rewrite rules if needed
395 if ( current_user_can( apply_filters( 'rl_lightbox_settings_capability', $rl->options['capabilities']['active'] ? 'edit_lightbox_settings' : 'manage_options' ) ) && isset( $_POST['flush_rules'] ) && isset( $_POST['option_page'], $_POST['action'], $_POST['responsive_lightbox_builder'], $_POST['_wpnonce'] ) && $_POST['option_page'] === 'responsive_lightbox_builder' && $_POST['action'] === 'update' && ( isset( $_POST['save_rl_builder'] ) || isset( $_POST['reset_rl_builder'] ) || isset( $_POST['save_responsive_lightbox_builder'] ) || isset( $_POST['reset_responsive_lightbox_builder'] ) ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'responsive_lightbox_builder-options' ) )
396 flush_rewrite_rules();
397 }
398
399 /**
400 * Load default settings.
401 *
402 * @global string $pagenow
403 *
404 * @return void
405 */
406 public function load_defaults() {
407 // Core settings data has been migrated to:
408 // - Responsive_Lightbox_Settings_Data::get_scripts()
409 // - Responsive_Lightbox_Settings_Data::get_image_titles()
410 // - Settings API page classes (class-settings-*.php)
411
412 // Initialize empty arrays for legacy add-on compatibility
413 // Add-ons populate these via legacy patterns and bridge converts them
414 $this->settings = [];
415 $this->tabs = [];
416 $this->scripts = [];
417 $this->image_titles = [];
418 }
419
420 /**
421 * Register options page
422 *
423 * @return void
424 */
425 public function admin_menu_options() {
426 $rl = Responsive_Lightbox();
427
428 // get master capability
429 $capability = apply_filters( 'rl_lightbox_settings_capability', $rl->options['capabilities']['active'] ? 'edit_lightbox_settings' : 'manage_options' );
430
431 // if capabilities are active, ensure admin-level users have the required capability
432 if ( $rl->options['capabilities']['active'] ) {
433 $user = wp_get_current_user();
434
435 // grant capability to users with manage_options (admins) who don't have it yet
436 if ( is_a( $user, 'WP_User' ) && $user->has_cap( 'manage_options' ) && ! $user->has_cap( $capability ) ) {
437 $user->add_cap( $capability );
438 }
439 }
440
441 // Register submenu entries for each settings tab so WP admin left menu
442 // behaves like native menus with visible child items on hover.
443 $api_pages = $rl->settings_api->get_pages();
444 $tabs = isset( $api_pages['settings']['tabs'] ) && is_array( $api_pages['settings']['tabs'] ) ? $api_pages['settings']['tabs'] : [];
445
446 if ( empty( $tabs ) )
447 return;
448
449 $parent_slug = 'responsive-lightbox-settings';
450 $submenu_root_tab = '';
451
452 foreach ( $tabs as $tab_key => $tab_data ) {
453 if ( ! empty( $tab_data['disabled'] ) )
454 continue;
455
456 $submenu_root_tab = $tab_key;
457 break;
458 }
459
460 foreach ( $tabs as $tab_key => $tab_data ) {
461 if ( ! empty( $tab_data['disabled'] ) )
462 continue;
463
464 $menu_title = ! empty( $tab_data['label'] ) ? $tab_data['label'] : ucfirst( str_replace( '_', ' ', $tab_key ) );
465 $menu_slug = ( $tab_key === $submenu_root_tab ) ? $parent_slug : $parent_slug . '&tab=' . $tab_key;
466
467 add_submenu_page(
468 $parent_slug,
469 __( 'Lightbox', 'responsive-lightbox' ),
470 $menu_title,
471 $capability,
472 $menu_slug,
473 [ $rl->settings_api, 'options_page' ]
474 );
475 }
476 }
477
478 /**
479 * Highlight parent menu for tabbed settings.
480 *
481 * @param string $parent_file Parent file.
482 * @return string
483 */
484 public function highlight_parent_menu( $parent_file ) {
485 $page_raw = isset( $_GET['page'] ) ? wp_unslash( $_GET['page'] ) : '';
486 $page_parts = $page_raw !== '' ? explode( '&', $page_raw, 2 ) : [ '' ];
487 $page = $page_parts[0] !== '' ? sanitize_key( $page_parts[0] ) : '';
488
489 if ( $page === 'responsive-lightbox-settings' )
490 return 'responsive-lightbox-settings';
491
492 return $parent_file;
493 }
494
495 /**
496 * Highlight submenu based on active settings tab.
497 *
498 * @param string $submenu_file Submenu file.
499 * @param string $parent_file Parent file.
500 * @return string
501 */
502 public function highlight_submenu( $submenu_file, $parent_file ) {
503 if ( $parent_file !== 'responsive-lightbox-settings' )
504 return $submenu_file;
505
506 $page_raw = isset( $_GET['page'] ) ? wp_unslash( $_GET['page'] ) : '';
507 $page_parts = $page_raw !== '' ? explode( '&', $page_raw, 2 ) : [ '' ];
508 $page = $page_parts[0] !== '' ? sanitize_key( $page_parts[0] ) : '';
509
510 if ( $page !== 'responsive-lightbox-settings' )
511 return $submenu_file;
512
513 $rl = Responsive_Lightbox();
514 $api_pages = $rl->settings_api->get_pages();
515 $tabs = isset( $api_pages['settings']['tabs'] ) && is_array( $api_pages['settings']['tabs'] ) ? $api_pages['settings']['tabs'] : [];
516
517 if ( empty( $tabs ) )
518 return 'responsive-lightbox-settings';
519
520 $submenu_root_tab = '';
521 foreach ( $tabs as $tab_key => $tab_data ) {
522 if ( ! empty( $tab_data['disabled'] ) )
523 continue;
524
525 $submenu_root_tab = $tab_key;
526 break;
527 }
528
529 if ( $submenu_root_tab === '' )
530 return 'responsive-lightbox-settings';
531
532 $page_args = [];
533 if ( ! empty( $page_parts[1] ) )
534 parse_str( $page_parts[1], $page_args );
535
536 $tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : ( isset( $page_args['tab'] ) ? sanitize_key( $page_args['tab'] ) : $submenu_root_tab );
537
538 if ( ! isset( $tabs[$tab] ) || ! empty( $tabs[$tab]['disabled'] ) )
539 $tab = $submenu_root_tab;
540
541 if ( $tab === $submenu_root_tab )
542 return 'responsive-lightbox-settings';
543
544 return 'responsive-lightbox-settings&tab=' . $tab;
545 }
546
547 /**
548 * Render options page stub.
549 *
550 * Settings API now handles all rendering. This method retained for backward compatibility
551 * with add-ons or hooks that may reference it.
552 *
553 * @return void
554 */
555 public function options_page() {
556 // Settings API handles rendering via class-settings-api.php
557 // Filter 'rl_render_settings_page' retained for backward compatibility
558 $tab_key = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : 'settings';
559
560 if ( apply_filters( 'rl_render_settings_page', true, $tab_key ) )
561 return;
562 }
563
564 /**
565 * Add new capability to manage options.
566 *
567 * @return string
568 */
569 public function manage_options_capability() {
570 return Responsive_Lightbox()->options['capabilities']['active'] ? 'edit_lightbox_settings' : 'manage_options';
571 }
572
573 /**
574 * Legacy settings validation wrapper.
575 *
576 * @deprecated Use Settings API tab validation instead.
577 *
578 * @param array $input Input data.
579 * @return array Validated data.
580 */
581 public function validate_settings( $input ) {
582 $rl = Responsive_Lightbox();
583
584 if ( isset( $rl->settings_api ) && $rl->settings_api instanceof Responsive_Lightbox_Settings_API ) {
585 return $rl->settings_api->validate_settings( $input );
586 }
587
588 return $input;
589 }
590
591 /**
592 * Bridge legacy add-on settings to Settings API format.
593 *
594 * Converts legacy $this->settings arrays (from add-ons using old registration)
595 * into Settings API-compatible data structures. Minimal implementation for
596 * backward compatibility.
597 *
598 * @param array $data Settings API data from all tabs.
599 * @return array Enhanced data with legacy settings converted.
600 */
601 public function bridge_legacy_settings( $data ) {
602 // get main instance
603 $rl = Responsive_Lightbox();
604
605 // iterate through legacy settings (populated by add-ons)
606 foreach ( $this->settings as $tab_key => $legacy_tab ) {
607 // skip if already registered by Settings API
608 if ( isset( $data[$tab_key] ) )
609 continue;
610
611 // skip if no fields defined
612 if ( empty( $legacy_tab['fields'] ) || ! is_array( $legacy_tab['fields'] ) )
613 continue;
614
615 // convert legacy tab to Settings API format
616 $api_tab = [
617 'option_name' => ! empty( $legacy_tab['option_name'] ) ? $legacy_tab['option_name'] : 'responsive_lightbox_' . $tab_key,
618 'option_group' => ! empty( $legacy_tab['option_group'] ) ? $legacy_tab['option_group'] : 'responsive_lightbox_' . $tab_key,
619 'sections' => []
620 ];
621 if ( ! empty( $legacy_tab['callback'] ) ) {
622 $api_tab['validate'] = $legacy_tab['callback'];
623 }
624
625 // normalize fields and group into sections
626 if ( ! empty( $legacy_tab['sections'] ) && is_array( $legacy_tab['sections'] ) ) {
627 // legacy has sections - convert each
628 foreach ( $legacy_tab['sections'] as $section_id => $section ) {
629 $api_tab['sections'][$section_id] = [
630 'title' => ! empty( $section['title'] ) ? $section['title'] : '',
631 'description' => ! empty( $section['description'] ) ? $section['description'] : '',
632 'callback' => ! empty( $section['callback'] ) ? $section['callback'] : null,
633 'fields' => []
634 ];
635
636 // add fields that belong to this section
637 foreach ( $legacy_tab['fields'] as $field_id => $field ) {
638 if ( ! empty( $field['section'] ) && $field['section'] === $section_id ) {
639 $api_tab['sections'][$section_id]['fields'][$field_id] = $this->normalize_legacy_field( $field, $field_id, $section_id );
640 }
641 }
642 }
643 } else {
644 // no sections - create default section
645 $default_section = 'responsive_lightbox_' . $tab_key . '_fields';
646 $api_tab['sections'][$default_section] = [
647 'title' => '',
648 'description' => '',
649 'fields' => []
650 ];
651
652 // convert all fields
653 foreach ( $legacy_tab['fields'] as $field_id => $field ) {
654 $api_tab['sections'][$default_section]['fields'][$field_id] = $this->normalize_legacy_field( $field, $field_id, $default_section );
655 }
656 }
657
658 // add converted tab to data
659 $data[$tab_key] = $api_tab;
660 }
661
662 return $data;
663 }
664
665 /**
666 * Normalize legacy field definition to Settings API format.
667 *
668 * @param array $field Legacy field definition.
669 * @param string $field_id Field identifier.
670 * @param string $section_id Section identifier.
671 * @return array Normalized field.
672 */
673 private function normalize_legacy_field( $field, $field_id, $section_id ) {
674 // type normalization: legacy → API
675 $type_map = [
676 'switch' => 'boolean',
677 'color' => 'color_picker'
678 ];
679
680 $field_type = ! empty( $field['type'] ) ? $field['type'] : 'text';
681 if ( empty( $field['type'] ) )
682 $field['type'] = $field_type;
683 if ( isset( $type_map[$field_type] ) ) {
684 $field['type'] = $type_map[$field_type];
685 }
686
687 // ensure section key is present
688 $field['section'] = $section_id;
689
690 // handle multiple fields with subfields
691 if ( $field['type'] === 'multiple' && ! empty( $field['fields'] ) ) {
692 foreach ( $field['fields'] as $subfield_id => $subfield ) {
693 // normalize subfield types
694 $subfield_type = ! empty( $subfield['type'] ) ? $subfield['type'] : 'text';
695 if ( isset( $type_map[$subfield_type] ) ) {
696 $field['fields'][$subfield_id]['type'] = $type_map[$subfield_type];
697 }
698
699 // preserve callback and callback_args for custom subfields
700 if ( ! empty( $subfield['callback'] ) ) {
701 $field['fields'][$subfield_id]['callback'] = $subfield['callback'];
702 if ( ! empty( $subfield['callback_args'] ) ) {
703 $field['fields'][$subfield_id]['callback_args'] = $subfield['callback_args'];
704 }
705 }
706 }
707 }
708
709 // preserve top-level callback
710 if ( ! empty( $field['callback'] ) ) {
711 $field['callback'] = $field['callback'];
712 if ( ! empty( $field['callback_args'] ) ) {
713 $field['callback_args'] = $field['callback_args'];
714 }
715 }
716
717 return $field;
718 }
719 }
720