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 |