PluginProbe ʕ •ᴥ•ʔ
Responsive Lightbox & Gallery / 2.7.0
Responsive Lightbox & Gallery v2.7.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-settings.php
responsive-lightbox / includes Last commit date
providers 5 months ago settings 5 months ago class-fast-image.php 2 years ago class-folders.php 5 months ago class-frontend.php 5 months ago class-galleries.php 5 months ago class-multilang.php 2 years ago class-remote-library-api.php 5 months ago class-remote-library.php 5 months ago class-settings-api.php 5 months ago class-settings-data.php 5 months ago class-settings-pages.php 5 months ago class-settings.php 5 months ago class-tour.php 5 months ago class-welcome.php 2 years ago class-widgets.php 2 years ago functions.php 3 years ago
class-settings.php
620 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' ] );
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 * Get script option from scripts array.
220 *
221 * @since 2.6.1
222 * @param string $script Script key (e.g., 'swipebox', 'prettyphoto')
223 * @param string $option Option key (e.g., 'animations', 'themes')
224 * @return mixed Option value or null if not found
225 */
226 public function get_script_option( $script, $option ) {
227 _doing_it_wrong(
228 'Direct access to Responsive_Lightbox()->settings->scripts[]',
229 'Use Responsive_Lightbox()->settings->get_script_option() instead. Direct array access will be deprecated in a future version.',
230 '2.6.1'
231 );
232
233 $scripts = Responsive_Lightbox_Settings_Data::get_scripts();
234
235 if ( isset( $scripts[ $script ][ $option ] ) ) {
236 return $scripts[ $script ][ $option ];
237 }
238
239 return null;
240 }
241
242 /**
243 * Get all scripts array.
244 *
245 * @since 2.6.1
246 * @return array Scripts array
247 */
248 public function get_scripts() {
249 _doing_it_wrong(
250 'Direct access to Responsive_Lightbox()->settings->scripts',
251 'Use Responsive_Lightbox()->settings->get_scripts() instead. Direct array access will be deprecated in a future version.',
252 '2.6.1'
253 );
254
255 return Responsive_Lightbox_Settings_Data::get_scripts();
256 }
257
258 /**
259 * Get image titles array.
260 *
261 * @since 2.6.1
262 * @return array Image titles array
263 */
264 public function get_image_titles() {
265 _doing_it_wrong(
266 'Direct access to Responsive_Lightbox()->settings->image_titles',
267 'Use Responsive_Lightbox()->settings->get_image_titles() instead. Direct array access will be deprecated in a future version.',
268 '2.6.1'
269 );
270
271 return Responsive_Lightbox_Settings_Data::get_image_titles();
272 }
273
274 /**
275 * Check if a settings tab exists.
276 *
277 * @since 2.6.1
278 * @param string $tab Tab key
279 * @return bool True if tab exists, false otherwise
280 */
281 public function has_setting_tab( $tab ) {
282 return isset( $this->settings[ $tab ] );
283 }
284
285 /**
286 * Get settings key by option_name lookup.
287 *
288 * Used to reverse-map from WordPress option_page to internal settings key.
289 *
290 * @since 2.6.1
291 * @param string $option_name Option name to search for (e.g., 'responsive_lightbox_settings')
292 * @return string|null Settings key or null if not found
293 */
294 public function get_settings_key_by_option( $option_name ) {
295 foreach ( $this->settings as $id => $setting ) {
296 if ( isset( $setting['option_name'] ) && $setting['option_name'] === $option_name ) {
297 return $id;
298 }
299 }
300
301 // fallback: resolve from Settings API data
302 $settings_data = apply_filters( 'rl_settings_data', [] );
303 if ( is_array( $settings_data ) ) {
304 foreach ( $settings_data as $id => $setting ) {
305 if ( isset( $setting['option_name'] ) && $setting['option_name'] === $option_name ) {
306 return $id;
307 }
308 }
309 }
310
311 return null;
312 }
313
314 /**
315 * Get full setting definition (not just fields).
316 *
317 * Used when needing option_name, option_group, or other metadata.
318 *
319 * @since 2.6.1
320 * @param string $tab Tab key
321 * @return array|null Full setting definition or null if not found
322 */
323 public function get_setting_definition( $tab ) {
324 // Note: Accesses legacy structure directly; needed for metadata like option_name/option_group
325 // that isn't part of the fields array
326 if ( isset( $this->settings[ $tab ] ) ) {
327 return $this->settings[ $tab ];
328 }
329 return null;
330 }
331
332 /**
333 * Initialize additional stuff for builder.
334 *
335 * @return void
336 */
337 public function init_builder() {
338 // get main instance
339 $rl = Responsive_Lightbox();
340
341 // Category options now populated by Settings API (class-settings-builder.php)
342 // Legacy code removed - no longer writing to $this->settings
343
344 // flush rewrite rules if needed
345 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'] ) ) && check_admin_referer( 'responsive_lightbox_builder-options', '_wpnonce' ) !== false )
346 flush_rewrite_rules();
347 }
348
349 /**
350 * Load default settings.
351 *
352 * @global string $pagenow
353 *
354 * @return void
355 */
356 public function load_defaults() {
357 // Core settings data has been migrated to:
358 // - Responsive_Lightbox_Settings_Data::get_scripts()
359 // - Responsive_Lightbox_Settings_Data::get_image_titles()
360 // - Settings API page classes (class-settings-*.php)
361
362 // Initialize empty arrays for legacy add-on compatibility
363 // Add-ons populate these via legacy patterns and bridge converts them
364 $this->settings = [];
365 $this->tabs = [];
366 $this->scripts = [];
367 $this->image_titles = [];
368 }
369
370 /**
371 * Register options page
372 *
373 * @return void
374 */
375 public function admin_menu_options() {
376 $rl = Responsive_Lightbox();
377
378 // get master capability
379 $capability = apply_filters( 'rl_lightbox_settings_capability', $rl->options['capabilities']['active'] ? 'edit_lightbox_settings' : 'manage_options' );
380
381 // if capabilities are active, ensure admin-level users have the required capability
382 if ( $rl->options['capabilities']['active'] ) {
383 $user = wp_get_current_user();
384
385 // grant capability to users with manage_options (admins) who don't have it yet
386 if ( is_a( $user, 'WP_User' ) && $user->has_cap( 'manage_options' ) && ! $user->has_cap( $capability ) ) {
387 $user->add_cap( $capability );
388 }
389 }
390
391 // Settings API handles menu registration via prepare_pages()
392 // Filter 'rl_use_settings_api_menus' retained for backward compatibility but always true
393 }
394
395 /**
396 * Highlight parent menu for tabbed settings.
397 *
398 * @param string $parent_file Parent file.
399 * @return string
400 */
401 public function highlight_parent_menu( $parent_file ) {
402 $page_raw = isset( $_GET['page'] ) ? wp_unslash( $_GET['page'] ) : '';
403 $page_parts = $page_raw !== '' ? explode( '&', $page_raw, 2 ) : [ '' ];
404 $page = $page_parts[0] !== '' ? sanitize_key( $page_parts[0] ) : '';
405
406 if ( $page === 'responsive-lightbox-settings' )
407 return 'responsive-lightbox-settings';
408
409 return $parent_file;
410 }
411
412 /**
413 * Highlight submenu for tabbed settings.
414 *
415 * @param string $submenu_file Submenu file.
416 * @param string $parent_file Parent file.
417 * @return string
418 */
419 public function highlight_submenu( $submenu_file, $parent_file ) {
420 if ( $parent_file !== 'responsive-lightbox-settings' )
421 return $submenu_file;
422
423 $page_raw = isset( $_GET['page'] ) ? wp_unslash( $_GET['page'] ) : '';
424 $page_parts = $page_raw !== '' ? explode( '&', $page_raw, 2 ) : [ '' ];
425 $page = $page_parts[0] !== '' ? sanitize_key( $page_parts[0] ) : '';
426 $page_args = [];
427
428 if ( ! empty( $page_parts[1] ) )
429 parse_str( $page_parts[1], $page_args );
430
431 if ( $page !== 'responsive-lightbox-settings' )
432 return $submenu_file;
433
434 $tab_key = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : ( isset( $page_args['tab'] ) ? sanitize_key( $page_args['tab'] ) : 'settings' );
435
436 $target = 'responsive-lightbox-settings&tab=' . $tab_key;
437 $menu = isset( $GLOBALS['submenu']['responsive-lightbox-settings'] ) ? $GLOBALS['submenu']['responsive-lightbox-settings'] : [];
438
439 foreach ( $menu as $item ) {
440 if ( isset( $item[2] ) && $item[2] === $target )
441 return $target;
442 }
443
444 return $submenu_file;
445 }
446
447 /**
448 * Render options page stub.
449 *
450 * Settings API now handles all rendering. This method retained for backward compatibility
451 * with add-ons or hooks that may reference it.
452 *
453 * @return void
454 */
455 public function options_page() {
456 // Settings API handles rendering via class-settings-api.php
457 // Filter 'rl_render_settings_page' retained for backward compatibility
458 $tab_key = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : 'settings';
459
460 if ( apply_filters( 'rl_render_settings_page', true, $tab_key ) )
461 return;
462 }
463
464 /**
465 * Add new capability to manage options.
466 *
467 * @return string
468 */
469 public function manage_options_capability() {
470 return Responsive_Lightbox()->options['capabilities']['active'] ? 'edit_lightbox_settings' : 'manage_options';
471 }
472
473 /**
474 * Legacy settings validation wrapper.
475 *
476 * @deprecated Use Settings API tab validation instead.
477 *
478 * @param array $input Input data.
479 * @return array Validated data.
480 */
481 public function validate_settings( $input ) {
482 $rl = Responsive_Lightbox();
483
484 if ( isset( $rl->settings_api ) && $rl->settings_api instanceof Responsive_Lightbox_Settings_API ) {
485 return $rl->settings_api->validate_settings( $input );
486 }
487
488 return $input;
489 }
490
491 /**
492 * Bridge legacy add-on settings to Settings API format.
493 *
494 * Converts legacy $this->settings arrays (from add-ons using old registration)
495 * into Settings API-compatible data structures. Minimal implementation for
496 * backward compatibility.
497 *
498 * @param array $data Settings API data from all tabs.
499 * @return array Enhanced data with legacy settings converted.
500 */
501 public function bridge_legacy_settings( $data ) {
502 // get main instance
503 $rl = Responsive_Lightbox();
504
505 // iterate through legacy settings (populated by add-ons)
506 foreach ( $this->settings as $tab_key => $legacy_tab ) {
507 // skip if already registered by Settings API
508 if ( isset( $data[$tab_key] ) )
509 continue;
510
511 // skip if no fields defined
512 if ( empty( $legacy_tab['fields'] ) || ! is_array( $legacy_tab['fields'] ) )
513 continue;
514
515 // convert legacy tab to Settings API format
516 $api_tab = [
517 'option_name' => ! empty( $legacy_tab['option_name'] ) ? $legacy_tab['option_name'] : 'responsive_lightbox_' . $tab_key,
518 'option_group' => ! empty( $legacy_tab['option_group'] ) ? $legacy_tab['option_group'] : 'responsive_lightbox_' . $tab_key,
519 'sections' => []
520 ];
521 if ( ! empty( $legacy_tab['callback'] ) ) {
522 $api_tab['validate'] = $legacy_tab['callback'];
523 }
524
525 // normalize fields and group into sections
526 if ( ! empty( $legacy_tab['sections'] ) && is_array( $legacy_tab['sections'] ) ) {
527 // legacy has sections - convert each
528 foreach ( $legacy_tab['sections'] as $section_id => $section ) {
529 $api_tab['sections'][$section_id] = [
530 'title' => ! empty( $section['title'] ) ? $section['title'] : '',
531 'description' => ! empty( $section['description'] ) ? $section['description'] : '',
532 'callback' => ! empty( $section['callback'] ) ? $section['callback'] : null,
533 'fields' => []
534 ];
535
536 // add fields that belong to this section
537 foreach ( $legacy_tab['fields'] as $field_id => $field ) {
538 if ( ! empty( $field['section'] ) && $field['section'] === $section_id ) {
539 $api_tab['sections'][$section_id]['fields'][$field_id] = $this->normalize_legacy_field( $field, $field_id, $section_id );
540 }
541 }
542 }
543 } else {
544 // no sections - create default section
545 $default_section = 'responsive_lightbox_' . $tab_key . '_fields';
546 $api_tab['sections'][$default_section] = [
547 'title' => '',
548 'description' => '',
549 'fields' => []
550 ];
551
552 // convert all fields
553 foreach ( $legacy_tab['fields'] as $field_id => $field ) {
554 $api_tab['sections'][$default_section]['fields'][$field_id] = $this->normalize_legacy_field( $field, $field_id, $default_section );
555 }
556 }
557
558 // add converted tab to data
559 $data[$tab_key] = $api_tab;
560 }
561
562 return $data;
563 }
564
565 /**
566 * Normalize legacy field definition to Settings API format.
567 *
568 * @param array $field Legacy field definition.
569 * @param string $field_id Field identifier.
570 * @param string $section_id Section identifier.
571 * @return array Normalized field.
572 */
573 private function normalize_legacy_field( $field, $field_id, $section_id ) {
574 // type normalization: legacy → API
575 $type_map = [
576 'switch' => 'boolean',
577 'color' => 'color_picker'
578 ];
579
580 $field_type = ! empty( $field['type'] ) ? $field['type'] : 'text';
581 if ( empty( $field['type'] ) )
582 $field['type'] = $field_type;
583 if ( isset( $type_map[$field_type] ) ) {
584 $field['type'] = $type_map[$field_type];
585 }
586
587 // ensure section key is present
588 $field['section'] = $section_id;
589
590 // handle multiple fields with subfields
591 if ( $field['type'] === 'multiple' && ! empty( $field['fields'] ) ) {
592 foreach ( $field['fields'] as $subfield_id => $subfield ) {
593 // normalize subfield types
594 $subfield_type = ! empty( $subfield['type'] ) ? $subfield['type'] : 'text';
595 if ( isset( $type_map[$subfield_type] ) ) {
596 $field['fields'][$subfield_id]['type'] = $type_map[$subfield_type];
597 }
598
599 // preserve callback and callback_args for custom subfields
600 if ( ! empty( $subfield['callback'] ) ) {
601 $field['fields'][$subfield_id]['callback'] = $subfield['callback'];
602 if ( ! empty( $subfield['callback_args'] ) ) {
603 $field['fields'][$subfield_id]['callback_args'] = $subfield['callback_args'];
604 }
605 }
606 }
607 }
608
609 // preserve top-level callback
610 if ( ! empty( $field['callback'] ) ) {
611 $field['callback'] = $field['callback'];
612 if ( ! empty( $field['callback_args'] ) ) {
613 $field['callback_args'] = $field['callback_args'];
614 }
615 }
616
617 return $field;
618 }
619 }
620