balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

class-redux-api.php (51267B)


      1 <?php // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
      2 /**
      3  * Redux Framework API Class
      4  * Makes instantiating a Redux object an absolute piece of cake.
      5  *
      6  * @package     Redux_Framework
      7  * @author      Dovy Paukstys
      8  * @subpackage  Core
      9  */
     10 
     11 // Exit if accessed directly.
     12 defined( 'ABSPATH' ) || exit;
     13 
     14 // Don't duplicate me!
     15 if ( ! class_exists( 'Redux', false ) ) {
     16 
     17 	/**
     18 	 * Redux API Class
     19 	 * Simple API for Redux Framework
     20 	 *
     21 	 * @since       3.0.0
     22 	 */
     23 	class Redux {
     24 
     25 
     26 		/**
     27 		 *  Option fields.
     28 		 *
     29 		 * @var array
     30 		 */
     31 		public static $fields = array();
     32 
     33 		/**
     34 		 * Option sections.
     35 		 *
     36 		 * @var array
     37 		 */
     38 		public static $sections = array();
     39 
     40 		/**
     41 		 * Option defaults.
     42 		 *
     43 		 * @var array
     44 		 */
     45 		public static $options_defaults = array();
     46 
     47 		/**
     48 		 * Option help array.
     49 		 *
     50 		 * @var array
     51 		 */
     52 		public static $help = array();
     53 
     54 		/**
     55 		 * Option global args.
     56 		 *
     57 		 * @var array
     58 		 */
     59 		public static $args = array();
     60 
     61 		/**
     62 		 * Option section priorities.
     63 		 *
     64 		 * @var array
     65 		 */
     66 		public static $priority = array();
     67 
     68 		/**
     69 		 * Panel validations errors.
     70 		 *
     71 		 * @var array
     72 		 */
     73 		public static $errors = array();
     74 
     75 		/**
     76 		 * Init.
     77 		 *
     78 		 * @var array
     79 		 */
     80 		public static $init = array();
     81 
     82 		/**
     83 		 * Delay Init opt_names
     84 		 *
     85 		 * @var array
     86 		 */
     87 		public static $delay_init = array();
     88 
     89 		/**
     90 		 * Extension list.
     91 		 *
     92 		 * @var array
     93 		 */
     94 		public static $extensions = array();
     95 
     96 		/**
     97 		 * Extensions in use.
     98 		 *
     99 		 * @var array
    100 		 */
    101 		public static $uses_extensions = array();
    102 
    103 		/**
    104 		 * Extension paths.
    105 		 *
    106 		 * @var array
    107 		 */
    108 		public static $extension_paths = array();
    109 
    110 		/**
    111 		 * Extension capability flag.
    112 		 *
    113 		 * @var boolean
    114 		 */
    115 		public static $extension_compatibility = false;
    116 
    117 		/**
    118 		 * Code to run at creation in instance.
    119 		 */
    120 		public static function load() {
    121 			add_action( 'after_setup_theme', array( 'Redux', 'create_redux' ) );
    122 			add_action( 'init', array( 'Redux', 'create_redux' ) );
    123 			add_action( 'switch_theme', array( 'Redux', 'create_redux' ) );
    124 
    125 			require_once Redux_Core::$dir . 'inc/extensions/metaboxes/class-redux-metaboxes-api.php';
    126 		}
    127 
    128 		/**
    129 		 * Delay init action function
    130 		 * Delays all Redux objects from loaded before `plugins_loaded` runs.
    131 		 */
    132 		public static function delay_init() {
    133 			if ( ! empty( self::$delay_init ) ) {
    134 
    135 				foreach ( self::$delay_init as $opt_name ) {
    136 					self::init( $opt_name );
    137 					$parent = Redux_Instances::get_instance( $opt_name );
    138 					// translators: This is only shown to developers, should not impact users.
    139 					$msg = sprintf(
    140 						'<strong>%s</strong><br /><code>%s</code> %s',
    141 						esc_html__( 'Warning, Premature Initialization', 'redux-framework' ),
    142 						'self::init("' . esc_html( $opt_name ) . '")',
    143 						// translators: This is only shown to developers, should not impact users.
    144 						sprintf( esc_html__( 'was run before the %s hook and was delayed to avoid errors.', 'redux-framework' ), '<code>plugins_loaded</code>' )
    145 					);
    146 
    147 					if ( isset( $parent->args ) ) {
    148 						$data = array(
    149 							'parent'  => $parent,
    150 							'type'    => 'error',
    151 							'msg'     => $msg,
    152 							'id'      => 'redux_init',
    153 							'dismiss' => true,
    154 						);
    155 
    156 						Redux_Admin_Notices::set_notice( $data );
    157 					}
    158 				}
    159 			}
    160 		}
    161 
    162 		/**
    163 		 * Init Redux object
    164 		 *
    165 		 * @param string $opt_name Panel opt_name.
    166 		 */
    167 		public static function init( string $opt_name = '' ) {
    168 			if ( ! empty( $opt_name ) ) {
    169 				if ( ! did_action( 'plugins_loaded' ) ) {
    170 
    171 					// We don't want to load before plugins_loaded EVER.
    172 					self::$delay_init[] = $opt_name;
    173 					add_action( 'plugins_loaded', array( 'Redux', 'delay_init' ) );
    174 				} else {
    175 
    176 					// The hook `plugins_loaded` has run, let's get going!
    177 					self::load_redux( $opt_name );
    178 
    179 					remove_action( 'setup_theme', array( 'Redux', 'create_redux' ) );
    180 				}
    181 			}
    182 		}
    183 
    184 		/**
    185 		 * Retrive ReduxFramework object.
    186 		 *
    187 		 * @param string $opt_name Panel opt_name.
    188 		 *
    189 		 * @return object|ReduxFramework
    190 		 */
    191 		public static function instance( string $opt_name ) {
    192 			return Redux_Instances::get_instance( $opt_name );
    193 		}
    194 
    195 		/**
    196 		 * Retrieve all ReduxFramework Instances.
    197 		 *
    198 		 * @return null|array|ReduxFramework[]
    199 		 */
    200 		public static function all_instances(): ?array {
    201 			return Redux_Instances::get_all_instances();
    202 		}
    203 
    204 		/**
    205 		 * Load external extensions.
    206 		 *
    207 		 * @param object $redux_framework ReduxFramework object.
    208 		 *
    209 		 * @deprecated No longer using camcelCase naming convensions.
    210 		 */
    211 		public static function loadExtensions( $redux_framework ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
    212 			self::load_extensions( $redux_framework );
    213 		}
    214 
    215 		/**
    216 		 * Load external extensions.
    217 		 *
    218 		 * @param object $redux_framework ReduxFramework object.
    219 		 */
    220 		public static function load_extensions( $redux_framework ) {
    221 			$instance_extensions = self::get_extensions( $redux_framework->args['opt_name'] );
    222 
    223 			if ( $instance_extensions ) {
    224 				foreach ( $instance_extensions as $name => $extension ) {
    225 					$old_class = str_replace( 'Redux_', 'ReduxFramework_', $extension['class'] );
    226 
    227 					if ( ! class_exists( $extension['class'] ) && ! class_exists( $old_class ) ) {
    228 						// In case you wanted override your override, hah.
    229 						// phpcs:ignore WordPress.NamingConventions.ValidHookName
    230 						$extension['path'] = apply_filters( 'redux/extension/' . $redux_framework->args['opt_name'] . '/' . $name, $extension['path'] );
    231 						if ( file_exists( $extension['path'] ) ) {
    232 							require_once $extension['path'];
    233 						}
    234 					}
    235 					if ( isset( $extension['field'] ) ) {
    236 						require_once $extension['field'];
    237 					}
    238 
    239 					if ( ! isset( $redux_framework->extensions[ $name ] ) ) {
    240 						$field_classes = array( $extension['class'], $old_class );
    241 						$ext_class     = Redux_Functions::class_exists_ex( $field_classes );
    242 						if ( false !== $ext_class ) {
    243 							$redux_framework->extensions[ $name ] = new $ext_class( $redux_framework );
    244 							// Backwards compatibility for extensions.
    245 							if ( ! is_subclass_of( $redux_framework->extensions[ $name ], 'Redux_Extension_Abstract' ) ) {
    246 								$new_class_name                       = $ext_class . '_extended';
    247 								self::$extension_compatibility        = true;
    248 								$redux_framework->extensions[ $name ] = Redux_Functions_Ex::extension_compatibility( $redux_framework, $extension['path'], $ext_class, $new_class_name, $name );
    249 							}
    250 						} elseif ( is_admin() && true === $redux_framework->args['dev_mode'] ) {
    251 							echo '<div id="message" class="error"><p>No class named <strong>' . esc_html( $extension['class'] ) . '</strong> exists. Please verify your extension path.</p></div>';
    252 						}
    253 					}
    254 				}
    255 			}
    256 		}
    257 
    258 		/**
    259 		 * Deprecated function to set extension path.
    260 		 *
    261 		 * @param string $extension Path.
    262 		 * @param bool   $folder    Set if path is a folder.
    263 		 *
    264 		 * @return bool|mixed
    265 		 * @deprecated No longer using cameCase naming convensions.
    266 		 */
    267 		public static function extensionPath( string $extension, bool $folder = true ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
    268 			return self::extension_path( $extension, $folder = true );
    269 		}
    270 
    271 		/**
    272 		 * Sets a path to an extension.
    273 		 *
    274 		 * @param string $extension Path to extension.
    275 		 * @param bool   $folder    Set if path is a folder.
    276 		 *
    277 		 * @return bool|mixed
    278 		 */
    279 		public static function extension_path( string $extension, bool $folder = true ) {
    280 			if ( ! isset( self::$extensions[ $extension ] ) ) {
    281 				return false;
    282 			}
    283 
    284 			$path = end( self::$extensions[ $extension ] );
    285 
    286 			if ( ! $folder ) {
    287 				return $path;
    288 			}
    289 
    290 			return dirname( $path );
    291 		}
    292 
    293 		/**
    294 		 * Deprecated function of Load Redux Framework.
    295 		 *
    296 		 * @param string $opt_name Panrl opt_name.
    297 		 *
    298 		 * @deprecated No longer using camelCase naming convensions.
    299 		 */
    300 		public static function loadRedux( string $opt_name = '' ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
    301 			self::load_redux( $opt_name );
    302 		}
    303 
    304 		/**
    305 		 * Load defaults values for a given opt_name.
    306 		 *
    307 		 * @param string $opt_name Panel opt_name.
    308 		 */
    309 		public static function set_defaults( string $opt_name = '' ) {
    310 			// Try to load the class if in the same directory, so the user only have to include the Redux API.
    311 			if ( ! class_exists( 'Redux_Options_Defaults' ) ) {
    312 				$file_check = trailingslashit( dirname( __FILE__ ) ) . 'class-redux-options-defaults.php';
    313 
    314 				if ( file_exists( dirname( $file_check ) ) ) {
    315 					include_once $file_check;
    316 					$file_check = trailingslashit( dirname( __FILE__ ) ) . 'class-redux-wordpress-data.php';
    317 					if ( file_exists( dirname( $file_check ) ) ) {
    318 						include_once $file_check;
    319 					}
    320 				}
    321 			}
    322 
    323 			if ( class_exists( 'Redux_Options_Defaults' ) && ! isset( self::$options_defaults[ $opt_name ] ) ) {
    324 				$sections                            = self::construct_sections( $opt_name );
    325 				$wordpress_data                      = ( ! class_exists( 'Redux_WordPress_Data' ) ) ? null : new Redux_WordPress_Data( $opt_name );
    326 				$options_defaults_class              = new Redux_Options_Defaults();
    327 				self::$options_defaults[ $opt_name ] = $options_defaults_class->default_values( $opt_name, $sections, $wordpress_data );
    328 				if ( ! isset( self::$args[ $opt_name ]['global_variable'] ) || ( '' === self::$args[ $opt_name ]['global_variable'] && false !== self::$args[ $opt_name ]['global_variable'] ) ) {
    329 					self::$args[ $opt_name ]['global_variable'] = str_replace( '-', '_', $opt_name );
    330 				}
    331 				if ( isset( self::$args[ $opt_name ]['global_variable'] ) && self::$args[ $opt_name ]['global_variable'] ) {
    332 					$option_global = self::$args[ $opt_name ]['global_variable'];
    333 
    334 					/**
    335 					 * Filter 'redux/options/{opt_name}/global_variable'
    336 					 *
    337 					 * @param array $value option value to set global_variable with
    338 					 */ global $$option_global;
    339 
    340 					// phpcs:ignore WordPress.NamingConventions.ValidHookName
    341 					$$option_global = apply_filters( 'redux/options/' . $opt_name . '/global_variable', self::$options_defaults[ $opt_name ] );
    342 				}
    343 			}
    344 		}
    345 
    346 		/**
    347 		 * Load Redux Framework.
    348 		 *
    349 		 * @param string $opt_name Panel opt_name.
    350 		 */
    351 		public static function load_redux( string $opt_name = '' ) {
    352 			if ( empty( $opt_name ) ) {
    353 				return;
    354 			}
    355 
    356 			if ( class_exists( 'ReduxFramework' ) ) {
    357 				if ( isset( self::$init[ $opt_name ] ) && ! empty( self::$init[ $opt_name ] ) ) {
    358 					return;
    359 				}
    360 			} else {
    361 				echo '<div id="message" class="error"><p>' . esc_html__( 'Redux Framework is not installed. Please install it.', 'redux-framework' ) . '</p></div>';
    362 
    363 				return;
    364 			}
    365 
    366 			$check = self::instance( $opt_name );
    367 
    368 			Redux_Functions_Ex::record_caller( $opt_name );
    369 
    370 			if ( isset( self::$init[ $opt_name ] ) && 1 === self::$init[ $opt_name ] ) {
    371 				return;
    372 			}
    373 
    374 			self::set_defaults( $opt_name );
    375 
    376 			$args     = self::construct_args( $opt_name );
    377 			$sections = self::construct_sections( $opt_name );
    378 
    379 			if ( isset( self::$uses_extensions[ $opt_name ] ) && ! empty( self::$uses_extensions[ $opt_name ] ) ) {
    380 				add_action( "redux/extensions/$opt_name/before", array( 'Redux', 'loadExtensions' ), 0 );
    381 			}
    382 
    383 			$redux                   = new ReduxFramework( $sections, $args );
    384 			self::$init[ $opt_name ] = 1;
    385 
    386 			if ( isset( $redux->args['opt_name'] ) && $redux->args['opt_name'] !== $opt_name ) {
    387 				self::$init[ $redux->args['opt_name'] ] = 1;
    388 			}
    389 		}
    390 
    391 		/**
    392 		 * Deprecated Create Redux instance.
    393 		 *
    394 		 * @deprecated No longer using camelCase naming convention.
    395 		 */
    396 		public static function createRedux() {       // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
    397 			self::create_redux();
    398 		}
    399 
    400 		/**
    401 		 * Create Redux instance.
    402 		 */
    403 		public static function create_redux() {
    404 			foreach ( self::$sections as $opt_name => $the_sections ) {
    405 				if ( ! empty( $the_sections ) ) {
    406 					if ( ! self::$init[ $opt_name ] ) {
    407 						self::loadRedux( $opt_name );
    408 					}
    409 				}
    410 			}
    411 		}
    412 
    413 		/**
    414 		 * Construct global arguments.
    415 		 *
    416 		 * @param string $opt_name Panel opt_name.
    417 		 *
    418 		 * @return array|mixed
    419 		 */
    420 		public static function construct_args( string $opt_name ) {
    421 			$args             = self::$args[ $opt_name ] ?? array();
    422 			$args['opt_name'] = $opt_name;
    423 
    424 			if ( ! isset( $args['menu_title'] ) ) {
    425 				$args['menu_title'] = ucfirst( $opt_name ) . ' Options';
    426 			}
    427 
    428 			if ( ! isset( $args['page_title'] ) ) {
    429 				$args['page_title'] = ucfirst( $opt_name ) . ' Options';
    430 			}
    431 
    432 			if ( ! isset( $args['page_slug'] ) ) {
    433 				$args['page_slug'] = $opt_name . '_options';
    434 			}
    435 
    436 			return $args;
    437 		}
    438 
    439 		/**
    440 		 * Construct option panel sections.
    441 		 *
    442 		 * @param string $opt_name Panel opt_name.
    443 		 *
    444 		 * @return array
    445 		 */
    446 		public static function construct_sections( string $opt_name ): array {
    447 			$sections = array();
    448 
    449 			if ( ! isset( self::$sections[ $opt_name ] ) ) {
    450 				return $sections;
    451 			}
    452 
    453 			foreach ( self::$sections[ $opt_name ] as $section_id => $section ) {
    454 				$section['fields'] = self::construct_fields( $opt_name, $section_id );
    455 				$p                 = $section['priority'];
    456 
    457 				while ( isset( $sections[ $p ] ) ) {
    458 					$p++;
    459 				}
    460 
    461 				$sections[ $p ] = $section;
    462 			}
    463 
    464 			ksort( $sections );
    465 
    466 			return $sections;
    467 		}
    468 
    469 		/**
    470 		 * Construct option panel fields.
    471 		 *
    472 		 * @param string $opt_name   Panel opt_name.
    473 		 * @param string $section_id ID of section.
    474 		 *
    475 		 * @return array
    476 		 */
    477 		public static function construct_fields( string $opt_name = '', string $section_id = '' ): array {
    478 			$fields = array();
    479 
    480 			if ( ! empty( self::$fields[ $opt_name ] ) ) {
    481 				foreach ( self::$fields[ $opt_name ] as $key => $field ) {
    482 					if ( $field['section_id'] === $section_id ) {
    483 						$p = esc_html( $field['priority'] );
    484 
    485 						while ( isset( $fields[ $p ] ) ) {
    486 							echo intval( $p++ );
    487 						}
    488 
    489 						$fields[ $p ] = $field;
    490 					}
    491 				}
    492 			}
    493 
    494 			ksort( $fields );
    495 
    496 			return $fields;
    497 		}
    498 
    499 		/**
    500 		 * Deprecated Retrieve panel section.
    501 		 *
    502 		 * @param string $opt_name Panel opt_name.
    503 		 * @param string $id       Section ID.
    504 		 *
    505 		 * @return bool
    506 		 * @deprecated No longer using camelCase naming convention.
    507 		 */
    508 		public static function getSection( string $opt_name = '', string $id = '' ): bool { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
    509 			return self::get_section( $opt_name, $id );
    510 		}
    511 
    512 		/**
    513 		 * Retrieve panel section.
    514 		 *
    515 		 * @param string     $opt_name Panel opt_name.
    516 		 * @param string|int $id       Section ID.
    517 		 *
    518 		 * @return bool|string|int
    519 		 */
    520 		public static function get_section( string $opt_name = '', $id = '' ) {
    521 			self::check_opt_name( $opt_name );
    522 
    523 			if ( ! empty( $opt_name ) && ! empty( $id ) ) {
    524 				if ( ! isset( self::$sections[ $opt_name ][ $id ] ) ) {
    525 					$id = Redux_Core::strtolower( sanitize_html_class( $id ) );
    526 				}
    527 
    528 				return self::$sections[ $opt_name ][ $id ] ?? false;
    529 			}
    530 
    531 			return false;
    532 		}
    533 
    534 		/**
    535 		 * Deprecated Create a section of the option panel.
    536 		 *
    537 		 * @param string $opt_name Panel opt_name.
    538 		 * @param array  $sections Section ID.
    539 		 *
    540 		 * @deprecated No longer using camelCase naming convention.
    541 		 */
    542 		public static function setSections( string $opt_name = '', array $sections = array() ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
    543 			if ( '' !== $opt_name ) {
    544 				Redux_Functions_Ex::record_caller( $opt_name );
    545 			}
    546 
    547 			self::set_sections( $opt_name, $sections );
    548 		}
    549 
    550 		/**
    551 		 * Create multiple sections of the option panel.
    552 		 *
    553 		 * @param string $opt_name Panel opt_name.
    554 		 * @param array  $sections Section ID.
    555 		 */
    556 		public static function set_sections( string $opt_name = '', array $sections = array() ) {
    557 			if ( empty( $sections ) || '' === $opt_name ) {
    558 				return;
    559 			}
    560 
    561 			self::check_opt_name( $opt_name );
    562 
    563 			Redux_Functions_Ex::record_caller( $opt_name );
    564 
    565 			foreach ( $sections as $section ) {
    566 				self::set_section( $opt_name, $section );
    567 			}
    568 		}
    569 
    570 		/**
    571 		 * Deprecated Retrieve all sections from the option panel.
    572 		 *
    573 		 * @param string $opt_name Panel opt_name.
    574 		 *
    575 		 * @return array|mixed
    576 		 * @deprecated No longer using camelCase naming convention.
    577 		 */
    578 		public static function getSections( string $opt_name = '' ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
    579 			return self::get_sections( $opt_name );
    580 		}
    581 
    582 		/**
    583 		 * Retrieve all sections from the option panel.
    584 		 *
    585 		 * @param string $opt_name Panel opt_name.
    586 		 *
    587 		 * @return array|mixed
    588 		 */
    589 		public static function get_sections( string $opt_name = '' ) {
    590 			self::check_opt_name( $opt_name );
    591 
    592 			if ( ! empty( self::$sections[ $opt_name ] ) ) {
    593 				return self::$sections[ $opt_name ];
    594 			}
    595 
    596 			return array();
    597 		}
    598 
    599 		/**
    600 		 * Deprecated Remove option panel by ID.
    601 		 *
    602 		 * @param string     $opt_name Panel opt_name.
    603 		 * @param string|int $id       Sectio ID.
    604 		 * @param bool       $fields   Remove fields.
    605 		 *
    606 		 * @deprecated No longer using camelCase naming convention.
    607 		 */
    608 		public static function removeSection( string $opt_name = '', $id = '', bool $fields = false ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
    609 			if ( '' !== $opt_name ) {
    610 				Redux_Functions_Ex::record_caller( $opt_name );
    611 			}
    612 
    613 			self::remove_section( $opt_name, $id, $fields );
    614 		}
    615 
    616 		/**
    617 		 * Remove option panel by ID.
    618 		 *
    619 		 * @param string     $opt_name Panel opt_name.
    620 		 * @param string|int $id       Sectio ID.
    621 		 * @param bool       $fields   Remove fields.
    622 		 */
    623 		public static function remove_section( string $opt_name = '', $id = '', bool $fields = false ) {
    624 			if ( '' !== $opt_name && '' !== $id ) {
    625 				Redux_Functions_Ex::record_caller( $opt_name );
    626 
    627 				if ( isset( self::$sections[ $opt_name ][ $id ] ) ) {
    628 					$priority = '';
    629 
    630 					foreach ( self::$sections[ $opt_name ] as $key => $section ) {
    631 						if ( $key === $id ) {
    632 							$priority = $section['priority'];
    633 							self::$priority[ $opt_name ]['sections']--;
    634 							unset( self::$sections[ $opt_name ][ $id ] );
    635 							continue;
    636 						}
    637 						if ( '' !== $priority ) {
    638 							$new_priority                        = $section['priority'];
    639 							$section['priority']                 = $priority;
    640 							self::$sections[ $opt_name ][ $key ] = $section;
    641 							$priority                            = $new_priority;
    642 						}
    643 					}
    644 
    645 					if ( isset( self::$fields[ $opt_name ] ) && ! empty( self::$fields[ $opt_name ] ) && true === $fields ) {
    646 						foreach ( self::$fields[ $opt_name ] as $key => $field ) {
    647 							if ( $field['section_id'] === $id ) {
    648 								unset( self::$fields[ $opt_name ][ $key ] );
    649 							}
    650 						}
    651 					}
    652 				}
    653 			}
    654 		}
    655 
    656 		/**
    657 		 * Deprecated Sets a single option panel section.
    658 		 *
    659 		 * @param string     $opt_name Panel opt_name.
    660 		 * @param array|null $section  Section data.
    661 		 *
    662 		 * @deprecated No longer using camelCase naming convention.
    663 		 */
    664 		public static function setSection( string $opt_name = '', ?array $section = array() ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
    665 			if ( '' !== $opt_name ) {
    666 				Redux_Functions_Ex::record_caller( $opt_name );
    667 			}
    668 
    669 			self::set_section( $opt_name, $section );
    670 		}
    671 
    672 		/**
    673 		 * Sets a single option panel section.
    674 		 *
    675 		 * @param string     $opt_name Panel opt_name.
    676 		 * @param array|null $section  Section data.
    677 		 * @param bool       $replace  Replaces section instead of creating a new one.
    678 		 */
    679 		public static function set_section( string $opt_name = '', ?array $section = array(), bool $replace = false ) {
    680 			if ( empty( $section ) || '' === $opt_name ) {
    681 				return;
    682 			}
    683 
    684 			self::check_opt_name( $opt_name );
    685 
    686 			Redux_Functions_Ex::record_caller( $opt_name );
    687 
    688 			if ( ! isset( $section['id'] ) ) {
    689 				if ( isset( $section['type'] ) && 'divide' === $section['type'] ) {
    690 					$section['id'] = time();
    691 				} else {
    692 					if ( isset( $section['title'] ) ) {
    693 						$section['id'] = Redux_Core::strtolower( sanitize_title( $section['title'] ) );
    694 					} else {
    695 						$section['id'] = time();
    696 					}
    697 				}
    698 
    699 				if ( isset( self::$sections[ $opt_name ][ $section['id'] ] ) && ! $replace ) {
    700 					$orig = $section['id'];
    701 					$i    = 0;
    702 
    703 					while ( isset( self::$sections[ $opt_name ][ $section['id'] ] ) ) {
    704 						$section['id'] = $orig . '_' . $i;
    705 						$i++;
    706 					}
    707 				} elseif ( isset( self::$sections[ $opt_name ][ $section['id'] ] ) && $replace ) {
    708 					// If replace is set, let's update the default values with these!
    709 					$fields = false;
    710 					if ( isset( self::$sections[ $opt_name ][ $section['id'] ]['fields'] ) && ! empty( self::$sections[ $opt_name ][ $section['id'] ]['fields'] ) ) {
    711 						$fields = self::$sections[ $opt_name ][ $section['id'] ]['fields'];
    712 					}
    713 					self::$sections[ $opt_name ][ $section['id'] ] = wp_parse_args( $section, self::$sections[ $opt_name ][ $section['id'] ] );
    714 					if ( ! empty( $fields ) ) {
    715 						if ( ! isset( self::$sections[ $opt_name ][ $section['id'] ]['fields'] ) || ( isset( self::$sections[ $opt_name ][ $section['id'] ]['fields'] ) && empty( self::$sections[ $opt_name ][ $section['id'] ]['fields'] ) ) ) {
    716 							self::$sections[ $opt_name ][ $section['id'] ]['fields'] = $fields;
    717 						}
    718 					}
    719 				}
    720 			}
    721 
    722 			if ( ! empty( $opt_name ) && is_array( $section ) && ! empty( $section ) ) {
    723 				if ( ! isset( $section['id'] ) && ! isset( $section['title'] ) ) {
    724 					self::$errors[ $opt_name ]['section']['missing_title'] = esc_html__( 'Unable to create a section due to missing id and title.', 'redux-framework' );
    725 
    726 					return;
    727 				}
    728 
    729 				if ( ! isset( $section['priority'] ) ) {
    730 					$section['priority'] = self::get_priority( $opt_name, 'sections' );
    731 				}
    732 
    733 				if ( isset( $section['fields'] ) ) {
    734 					if ( ! empty( $section['fields'] ) && is_array( $section['fields'] ) ) {
    735 						self::process_field_array( $opt_name, $section['id'], $section['fields'] );
    736 					}
    737 					unset( $section['fields'] );
    738 				}
    739 
    740 				self::$sections[ $opt_name ][ $section['id'] ] = $section;
    741 			} else {
    742 				self::$errors[ $opt_name ]['section']['empty'] = esc_html__( 'Unable to create a section due an empty section array or the section variable passed was not an array.', 'redux-framework' );
    743 			}
    744 		}
    745 
    746 		/**
    747 		 * Deprecated Hides an option panel section.
    748 		 *
    749 		 * @param string     $opt_name Panel opt_name.
    750 		 * @param string|int $id       Section ID.
    751 		 * @param bool       $hide     Flag to hide/show.
    752 		 *
    753 		 * @deprecated No longer using camelCase naming convention.
    754 		 */
    755 		public static function hideSection( string $opt_name = '', $id = '', bool $hide = true ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
    756 			if ( '' !== $opt_name ) {
    757 				Redux_Functions_Ex::record_caller( $opt_name );
    758 			}
    759 
    760 			self::hide_section( $opt_name, $id, $hide );
    761 		}
    762 
    763 		/**
    764 		 * Hides an option panel section.
    765 		 *
    766 		 * @param string     $opt_name Panel opt_name.
    767 		 * @param string|int $id       Section ID.
    768 		 * @param bool       $hide     Flag to hide/show.
    769 		 */
    770 		public static function hide_section( string $opt_name = '', $id = '', bool $hide = true ) {
    771 			self::check_opt_name( $opt_name );
    772 
    773 			if ( '' !== $opt_name && '' !== $id ) {
    774 				Redux_Functions_Ex::record_caller( $opt_name );
    775 
    776 				if ( isset( self::$sections[ $opt_name ][ $id ] ) ) {
    777 					self::$sections[ $opt_name ][ $id ]['hidden'] = $hide;
    778 				}
    779 			}
    780 		}
    781 
    782 		/**
    783 		 * Compiles field array data.
    784 		 *
    785 		 * @param string     $opt_name   Panel opt_name.
    786 		 * @param string|int $section_id Section ID.
    787 		 * @param array      $fields     Field data.
    788 		 */
    789 		private static function process_field_array( string $opt_name = '', $section_id = '', array $fields = array() ) {
    790 			if ( ! empty( $opt_name ) && ! empty( $section_id ) && is_array( $fields ) && ! empty( $fields ) ) {
    791 				foreach ( $fields as $field ) {
    792 					if ( ! is_array( $field ) ) {
    793 						continue;
    794 					}
    795 					self::set_field( $opt_name, $section_id, $field );
    796 				}
    797 			}
    798 		}
    799 
    800 		/**
    801 		 * Deprecated Retrieves an option panel field.
    802 		 *
    803 		 * @param string     $opt_name Panel opt_name.
    804 		 * @param string|int $id       Field ID.
    805 		 *
    806 		 * @return int|bool
    807 		 * @deprecated No longer using camelCase naming convention.
    808 		 */
    809 		public static function getField( string $opt_name = '', $id = '' ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
    810 			return self::get_field( $opt_name, $id );
    811 		}
    812 
    813 		/**
    814 		 * Retrieves an option panel field.
    815 		 *
    816 		 * @param string     $opt_name Panel opt_name.
    817 		 * @param string|int $id       Field ID.
    818 		 *
    819 		 * @return int|bool
    820 		 */
    821 		public static function get_field( string $opt_name = '', $id = '' ) {
    822 			self::check_opt_name( $opt_name );
    823 
    824 			if ( ! empty( $opt_name ) && ! empty( $id ) ) {
    825 				return self::$fields[ $opt_name ][ $id ] ?? false;
    826 			}
    827 
    828 			return false;
    829 		}
    830 
    831 		/**
    832 		 * Deprecated Hides an optio panel field.
    833 		 *
    834 		 * @param string     $opt_name Panel opt_name.
    835 		 * @param string|int $id       Field ID.
    836 		 * @param bool       $hide     Set hide/show.
    837 		 *
    838 		 * @deprecated No longer using camelCase naming convention.
    839 		 */
    840 		public static function hideField( string $opt_name = '', $id = '', bool $hide = true ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
    841 			if ( '' !== $opt_name ) {
    842 				Redux_Functions_Ex::record_caller( $opt_name );
    843 			}
    844 
    845 			self::hide_field( $opt_name, $id, $hide );
    846 		}
    847 
    848 		/**
    849 		 * Hides an option panel field.
    850 		 *
    851 		 * @param string     $opt_name Panel opt_name.
    852 		 * @param string|int $id       Field ID.
    853 		 * @param bool       $hide     Set hide/show.
    854 		 */
    855 		public static function hide_field( string $opt_name = '', $id = '', bool $hide = true ) {
    856 			self::check_opt_name( $opt_name );
    857 
    858 			if ( '' !== $opt_name && '' !== $id ) {
    859 				if ( isset( self::$fields[ $opt_name ][ $id ] ) ) {
    860 					Redux_Functions_Ex::record_caller( $opt_name );
    861 
    862 					if ( ! $hide ) {
    863 						self::$fields[ $opt_name ][ $id ]['class'] = str_replace( 'hidden', '', self::$fields[ $opt_name ][ $id ]['class'] );
    864 					} else {
    865 						self::$fields[ $opt_name ][ $id ]['class'] .= 'hidden';
    866 					}
    867 				}
    868 			}
    869 		}
    870 
    871 		/**
    872 		 * Deprecated Creates an option panel field.
    873 		 *
    874 		 * @param string     $opt_name   Panel opt_name.
    875 		 * @param string|int $section_id Section ID this field belongs to.
    876 		 * @param array      $field      Field data.
    877 		 *
    878 		 * @deprecated No longer using camelCase naming convention.
    879 		 */
    880 		public static function setField( string $opt_name = '', $section_id = '', array $field = array() ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
    881 			if ( '' !== $opt_name ) {
    882 				Redux_Functions_Ex::record_caller( $opt_name );
    883 			}
    884 
    885 			self::set_field( $opt_name, $section_id, $field );
    886 		}
    887 
    888 		/**
    889 		 * Creates an option panel field and adds to a section.
    890 		 *
    891 		 * @param string     $opt_name   Panel opt_name.
    892 		 * @param string|int $section_id Section ID this field belongs to.
    893 		 * @param array      $field      Field data.
    894 		 */
    895 		public static function set_field( string $opt_name = '', $section_id = '', array $field = array() ) {
    896 
    897 			if ( ! is_array( $field ) || empty( $field ) || '' === $opt_name || '' === $section_id ) {
    898 				return;
    899 			}
    900 
    901 			self::check_opt_name( $opt_name );
    902 
    903 			Redux_Functions_Ex::record_caller( $opt_name );
    904 
    905 			// Shim for the old method!
    906 			if ( is_array( $section_id ) ) {
    907 				$section_id_holder = $field;
    908 				$field             = $section_id;
    909 				if ( isset( $field['section_id'] ) ) {
    910 					$section_id = $field['section_id'];
    911 				}
    912 			}
    913 
    914 			$field['section_id'] = $section_id;
    915 
    916 			if ( ! isset( $field['priority'] ) ) {
    917 				$field['priority'] = self::get_priority( $opt_name, 'fields' );
    918 			}
    919 			$field['id'] = $field['id'] ?? "{$opt_name}_{$section_id}_{$field['type']}_" . wp_rand( 1, 9999 );
    920 
    921 			self::$fields[ $opt_name ][ $field['id'] ] = $field;
    922 		}
    923 
    924 		/**
    925 		 * Create multiple fields of the option panel and apply to a section.
    926 		 *
    927 		 * @param string     $opt_name   Panel opt_name.
    928 		 * @param int|string $section_id Section ID this field belongs to.
    929 		 * @param array      $fields     Array of field arrays.
    930 		 */
    931 		public static function set_fields( string $opt_name = '', $section_id = '', array $fields = array() ) {
    932 			if ( ! is_array( $fields ) || empty( $fields ) || '' === $opt_name || '' === $section_id ) {
    933 				return;
    934 			}
    935 
    936 			self::check_opt_name( $opt_name );
    937 
    938 			// phpcs:ignore WordPress.PHP.DevelopmentFunctions
    939 			Redux_Functions_Ex::record_caller( $opt_name );
    940 
    941 			foreach ( $fields as $field ) {
    942 				if ( is_array( $field ) ) {
    943 					self::set_field( $opt_name, $section_id, $field );
    944 				}
    945 			}
    946 		}
    947 
    948 		/**
    949 		 * Deprecated Removes an option panel field.
    950 		 *
    951 		 * @param string     $opt_name Panel opt_name.
    952 		 * @param string|int $id       Field ID.
    953 		 *
    954 		 * @return bool
    955 		 * @deprecated No longer using camelCase naming convention.
    956 		 */
    957 		public static function removeField( string $opt_name = '', $id = '' ): bool { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
    958 			if ( '' !== $opt_name ) {
    959 				Redux_Functions_Ex::record_caller( $opt_name );
    960 			}
    961 
    962 			return self::remove_field( $opt_name, $id );
    963 		}
    964 
    965 		/**
    966 		 * Removes an option panel field.
    967 		 *
    968 		 * @param string     $opt_name Panel opt_name.
    969 		 * @param string|int $id       Field ID.
    970 		 *
    971 		 * @return bool
    972 		 */
    973 		public static function remove_field( string $opt_name = '', $id = '' ): bool {
    974 			if ( '' !== $opt_name && '' !== $id ) {
    975 				self::check_opt_name( $opt_name );
    976 
    977 				Redux_Functions_Ex::record_caller( $opt_name );
    978 
    979 				if ( isset( self::$fields[ $opt_name ][ $id ] ) ) {
    980 					foreach ( self::$fields[ $opt_name ] as $key => $field ) {
    981 						if ( $key === $id ) {
    982 							$priority = $field['priority'];
    983 							self::$priority[ $opt_name ]['fields']--;
    984 							unset( self::$fields[ $opt_name ][ $id ] );
    985 							continue;
    986 						}
    987 
    988 						if ( isset( $priority ) && '' !== $priority ) {
    989 							$new_priority                      = $field['priority'];
    990 							$field['priority']                 = $priority;
    991 							self::$fields[ $opt_name ][ $key ] = $field;
    992 							$priority                          = $new_priority;
    993 						}
    994 					}
    995 				}
    996 			}
    997 
    998 			return false;
    999 		}
   1000 
   1001 		/**
   1002 		 * Deprecated Sets help tabs on option panel admin page.
   1003 		 *
   1004 		 * @param string $opt_name Panel opt_name.
   1005 		 * @param array  $tab      Tab data.
   1006 		 *
   1007 		 * @deprecated No longer using camelCase naming convention.
   1008 		 */
   1009 		public static function setHelpTab( string $opt_name = '', array $tab = array() ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
   1010 			self::set_help_tab( $opt_name, $tab );
   1011 		}
   1012 
   1013 		/**
   1014 		 * Sets help tabs on option panel admin page.
   1015 		 *
   1016 		 * @param string $opt_name Panel opt_name.
   1017 		 * @param array  $tab      Tab data.
   1018 		 */
   1019 		public static function set_help_tab( string $opt_name = '', array $tab = array() ) {
   1020 			if ( ! is_array( $tab ) && empty( $tab ) ) {
   1021 				return;
   1022 			}
   1023 
   1024 			self::check_opt_name( $opt_name );
   1025 
   1026 			if ( '' !== $opt_name ) {
   1027 				if ( ! isset( self::$args[ $opt_name ]['help_tabs'] ) ) {
   1028 					self::$args[ $opt_name ]['help_tabs'] = array();
   1029 				}
   1030 
   1031 				if ( isset( $tab['id'] ) ) {
   1032 					self::$args[ $opt_name ]['help_tabs'][] = $tab;
   1033 				} elseif ( is_array( end( $tab ) ) ) {
   1034 					foreach ( $tab as $tab_item ) {
   1035 						self::$args[ $opt_name ]['help_tabs'][] = $tab_item;
   1036 					}
   1037 				}
   1038 			}
   1039 		}
   1040 
   1041 		/**
   1042 		 * Deprecated Sets the help sidebar content.
   1043 		 *
   1044 		 * @param string $opt_name Panel opt_name.
   1045 		 * @param string $content  Content.
   1046 		 *
   1047 		 * @deprecated No longer using camelCase naming convention.
   1048 		 */
   1049 		public static function setHelpSidebar( string $opt_name = '', string $content = '' ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
   1050 			self::set_help_sidebar( $opt_name, $content );
   1051 		}
   1052 
   1053 		/**
   1054 		 * Sets the help sidebar content.
   1055 		 *
   1056 		 * @param string $opt_name Panel opt_name.
   1057 		 * @param string $content  Content.
   1058 		 */
   1059 		public static function set_help_sidebar( string $opt_name = '', string $content = '' ) {
   1060 			if ( '' === $content || '' === $opt_name ) {
   1061 				return;
   1062 			}
   1063 			self::check_opt_name( $opt_name );
   1064 
   1065 			self::$args[ $opt_name ]['help_sidebar'] = $content;
   1066 		}
   1067 
   1068 		/**
   1069 		 * Deprecated Sets option panel global arguments.
   1070 		 *
   1071 		 * @param string $opt_name Panel opt_name.
   1072 		 * @param array  $args     Argument data.
   1073 		 *
   1074 		 * @deprecated No longer using camelCase naming convention.
   1075 		 */
   1076 		public static function setArgs( string $opt_name = '', array $args = array() ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
   1077 			if ( '' !== $opt_name ) {
   1078 				Redux_Functions_Ex::record_caller( $opt_name );
   1079 			}
   1080 
   1081 			self::set_args( $opt_name, $args );
   1082 		}
   1083 
   1084 		/**
   1085 		 * Sets option panel global arguments.
   1086 		 *
   1087 		 * @param string $opt_name Panel opt_name.
   1088 		 * @param array  $args     Argument data.
   1089 		 */
   1090 		public static function set_args( string $opt_name = '', array $args = array() ) {
   1091 			if ( empty( $args ) || '' === $opt_name ) {
   1092 				return;
   1093 			}
   1094 
   1095 			self::check_opt_name( $opt_name );
   1096 
   1097 			Redux_Functions_Ex::record_caller( $opt_name );
   1098 
   1099 			if ( is_array( $args ) ) {
   1100 				if ( isset( self::$args[ $opt_name ] ) && isset( self::$args[ $opt_name ]['clearArgs'] ) ) {
   1101 					self::$args[ $opt_name ] = array();
   1102 				}
   1103 				self::$args[ $opt_name ] = wp_parse_args( $args, self::$args[ $opt_name ] );
   1104 			}
   1105 		}
   1106 
   1107 		/**
   1108 		 * Set's developer key for premium services.
   1109 		 *
   1110 		 * @param string       $opt_name Panel opt_name.
   1111 		 * @param string|array $arg      Args data.
   1112 		 */
   1113 		public static function set_developer( string $opt_name = '', $arg = '' ) {
   1114 			if ( empty( $arg ) || '' === $opt_name ) {
   1115 				return;
   1116 			}
   1117 
   1118 			self::check_opt_name( $opt_name );
   1119 
   1120 			Redux_Functions_Ex::record_caller( $opt_name );
   1121 
   1122 			self::$args[ $opt_name ]['developer'] = $arg;
   1123 		}
   1124 
   1125 		/**
   1126 		 * Deprecated Retrives option panel global arguemnt array.
   1127 		 *
   1128 		 * @param string $opt_name Panel opt_name.
   1129 		 *
   1130 		 * @return mixed
   1131 		 * @deprecated No longer camelCase naming convention.
   1132 		 */
   1133 		public static function getArgs( string $opt_name = '' ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
   1134 			return self::get_args( $opt_name );
   1135 		}
   1136 
   1137 		/**
   1138 		 * Retrives option panel global arguemnt array.
   1139 		 *
   1140 		 * @param string $opt_name Panel opt_name.
   1141 		 * @param string $key      Argument key name to be returned.
   1142 		 *
   1143 		 * @return mixed|null|array
   1144 		 */
   1145 		public static function get_args( string $opt_name = '', string $key = '' ) {
   1146 			self::check_opt_name( $opt_name );
   1147 
   1148 			if ( ! empty( $opt_name ) && ! empty( $key ) ) {
   1149 				if ( ! empty( self::$args[ $opt_name ] ) ) {
   1150 					return self::$args[ $opt_name ][ $key ];
   1151 				} else {
   1152 					return null;
   1153 				}
   1154 			} elseif ( ! empty( $opt_name ) && ! empty( self::$args[ $opt_name ] ) ) {
   1155 				return self::$args[ $opt_name ];
   1156 			}
   1157 		}
   1158 
   1159 		/**
   1160 		 * Deprecated Retrieves a single global argument.
   1161 		 *
   1162 		 * @param string $opt_name Panel opt_name.
   1163 		 * @param string $key      Argument name.
   1164 		 *
   1165 		 * @return mixed
   1166 		 * @deprecated No longer using camelCase naming convention and using singular function self::get_args() now.
   1167 		 */
   1168 		public static function getArg( string $opt_name = '', string $key = '' ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
   1169 			return self::get_args( $opt_name, $key );
   1170 		}
   1171 
   1172 		/**
   1173 		 * Retrieves a single global argument.
   1174 		 *
   1175 		 * @param string $opt_name Panel opt_name.
   1176 		 * @param string $key      Argument name.
   1177 		 *
   1178 		 * @return mixed|array|null
   1179 		 */
   1180 		public static function get_arg( string $opt_name = '', string $key = '' ) {
   1181 			self::check_opt_name( $opt_name );
   1182 
   1183 			if ( ! empty( $opt_name ) && ! empty( $key ) && ! empty( self::$args[ $opt_name ] ) ) {
   1184 				return self::$args[ $opt_name ][ $key ];
   1185 			} else {
   1186 				return null;
   1187 			}
   1188 		}
   1189 
   1190 		/**
   1191 		 * Deprecated Retrieves single option from the database.
   1192 		 *
   1193 		 * @param string       $opt_name Panel opt_name.
   1194 		 * @param string       $key      Option key.
   1195 		 * @param string|array $default  Default value.
   1196 		 *
   1197 		 * @return mixed
   1198 		 * @deprecated No longer using camelCase naming convention.
   1199 		 */
   1200 		public static function getOption( string $opt_name = '', string $key = '', $default = '' ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
   1201 			return self::get_option( $opt_name, $key );
   1202 		}
   1203 
   1204 		/**
   1205 		 * Retrieves meta for a given post page, IE WordPress meta values
   1206 		 *
   1207 		 * @param string $opt_name Panel opt_name.
   1208 		 * @param mixed  $the_post Post object to denote the current post, or custom.
   1209 		 * @param string $key      Option key.
   1210 		 * @param mixed  $default  Default value.
   1211 		 *
   1212 		 * @return mixed
   1213 		 */
   1214 		public static function get_post_meta( string $opt_name = '', $the_post = array(), string $key = '', $default = null ) {
   1215 			self::check_opt_name( $opt_name );
   1216 
   1217 			if ( empty( $opt_name ) ) {
   1218 				return;
   1219 			}
   1220 
   1221 			global $post;
   1222 
   1223 			$redux = ReduxFrameworkInstances::get_instance( $opt_name );
   1224 
   1225 			// We don't ever need to specify advanced_metaboxes here as all function for metaboxes are core,
   1226 			// and thus, metabox_lite.  The extension handles its own functions and is handled by this condition. - kp.
   1227 			$metaboxes = $redux->extensions['metaboxes'];
   1228 
   1229 			if ( null === $default || '' === $default ) {
   1230 				$default = self::get_option( $opt_name, $key );
   1231 			}
   1232 
   1233 			if ( isset( $the_post ) && is_array( $the_post ) ) {
   1234 				$the_post = $post;
   1235 			} elseif ( ! isset( $the_post ) || 0 === $the_post ) {
   1236 				return $default;
   1237 			} elseif ( is_numeric( $the_post ) ) {
   1238 				$the_post = get_post( $the_post );
   1239 			} elseif ( ! is_object( $the_post ) ) {
   1240 				$the_post = $post;
   1241 			}
   1242 
   1243 			$default = self::get_option( $opt_name, $key );
   1244 
   1245 			return $metaboxes->get_values( $the_post, $key, $default );
   1246 		}
   1247 
   1248 		/**
   1249 		 * Retrieves single option from the database.
   1250 		 *
   1251 		 * @param string $opt_name Panel opt_name.
   1252 		 * @param string $key      Option key.
   1253 		 * @param mixed  $default  Default value.
   1254 		 *
   1255 		 * @return mixed
   1256 		 */
   1257 		public static function get_option( string $opt_name = '', string $key = '', $default = null ) {
   1258 			self::check_opt_name( $opt_name );
   1259 
   1260 			// TODO - Add metaboxes magic here!
   1261 			if ( ! empty( $opt_name ) && ! empty( $key ) ) {
   1262 				global $$opt_name;
   1263 
   1264 				if ( empty( $$opt_name ) ) {
   1265 					$values    = get_option( $opt_name );
   1266 					$$opt_name = $values;
   1267 				} else {
   1268 					$values = $$opt_name;
   1269 				}
   1270 
   1271 				if ( ! isset( $values[ $key ] ) ) {
   1272 					if ( null === $default ) {
   1273 						$field = self::get_field( $opt_name, $key );
   1274 
   1275 						if ( false !== $field ) {
   1276 							$defaults_class = new Redux_Options_Defaults();
   1277 							$sections       = self::construct_sections( $opt_name );
   1278 							$defaults       = $defaults_class->default_values( $opt_name, $sections );
   1279 
   1280 							if ( isset( $defaults[ $key ] ) ) {
   1281 								$default = $defaults[ $key ];
   1282 							}
   1283 						}
   1284 					}
   1285 				}
   1286 
   1287 				if ( ! empty( $subkeys ) && is_array( $subkeys ) ) {
   1288 					$value = $default;
   1289 
   1290 					if ( isset( $values[ $key ] ) ) {
   1291 						$count = count( $subkeys );
   1292 
   1293 						if ( 1 === $count ) {
   1294 							$value = $values[ $key ][ $subkeys[1] ] ?? $default;
   1295 						} elseif ( 2 === $count ) {
   1296 							if ( isset( $values[ $key ][ $subkeys[1] ] ) ) {
   1297 								$value = $values[ $key ][ $subkeys[1] ][ $subkeys[2] ] ?? $default;
   1298 							}
   1299 						} elseif ( 3 === $count ) {
   1300 							if ( isset( $values[ $key ][ $subkeys[1] ] ) ) {
   1301 								if ( isset( $values[ $key ][ $subkeys[1] ][ $subkeys[2] ] ) ) {
   1302 									$value = $values[ $key ][ $subkeys[1] ][ $subkeys[2] ][ $subkeys[3] ] ?? $default;
   1303 								}
   1304 							}
   1305 						}
   1306 					}
   1307 				} else {
   1308 					$value = $values[ $key ] ?? $default;
   1309 				}
   1310 
   1311 				return $value;
   1312 			} else {
   1313 				return false;
   1314 			}
   1315 		}
   1316 
   1317 		/**
   1318 		 * Deprecated Sets an option into the database.
   1319 		 *
   1320 		 * @param string $opt_name Panel opt_name.
   1321 		 * @param string $key      Option key.
   1322 		 * @param mixed  $option   Option value.
   1323 		 *
   1324 		 * @return bool
   1325 		 * @deprecated No longer using camelCase naming convention.
   1326 		 */
   1327 		public static function setOption( string $opt_name = '', string $key = '', $option = '' ): bool { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
   1328 			if ( '' !== $opt_name ) {
   1329 				Redux_Functions_Ex::record_caller( $opt_name );
   1330 			}
   1331 
   1332 			return self::set_option( $opt_name, $key, $option );
   1333 		}
   1334 
   1335 		/**
   1336 		 * Sets an option into the database.
   1337 		 *
   1338 		 * @param string $opt_name Panel opt_name.
   1339 		 * @param string $key      Option key.
   1340 		 * @param mixed  $option   Option value.
   1341 		 *
   1342 		 * @return bool
   1343 		 */
   1344 		public static function set_option( string $opt_name = '', string $key = '', $option = '' ): bool {
   1345 			if ( '' === $key ) {
   1346 				return false;
   1347 			}
   1348 
   1349 			self::check_opt_name( $opt_name );
   1350 
   1351 			Redux_Functions_Ex::record_caller( $opt_name );
   1352 
   1353 			if ( '' !== $opt_name ) {
   1354 				$redux         = get_option( $opt_name );
   1355 				$redux[ $key ] = $option;
   1356 
   1357 				return update_option( $opt_name, $redux );
   1358 			} else {
   1359 				return false;
   1360 			}
   1361 		}
   1362 
   1363 		/**
   1364 		 * Get next availablt priority for field/section.
   1365 		 *
   1366 		 * @param string $opt_name Panel opt_name.
   1367 		 * @param string $type     Field or section.
   1368 		 *
   1369 		 * @return mixed
   1370 		 */
   1371 		public static function get_priority( string $opt_name, string $type ) {
   1372 			$priority                              = self::$priority[ $opt_name ][ $type ];
   1373 			self::$priority[ $opt_name ][ $type ] += 1;
   1374 
   1375 			return $priority;
   1376 		}
   1377 
   1378 		/**
   1379 		 * Check opt_name integrity.
   1380 		 *
   1381 		 * @param string $opt_name Panel opt_name.
   1382 		 */
   1383 		public static function check_opt_name( string $opt_name = '' ) {
   1384 			if ( empty( $opt_name ) || is_array( $opt_name ) ) {
   1385 				return;
   1386 			}
   1387 
   1388 			if ( ! isset( self::$sections[ $opt_name ] ) ) {
   1389 				self::$sections[ $opt_name ]             = array();
   1390 				self::$priority[ $opt_name ]['sections'] = 1;
   1391 			}
   1392 
   1393 			if ( ! isset( self::$args[ $opt_name ] ) ) {
   1394 				self::$args[ $opt_name ]             = array();
   1395 				self::$priority[ $opt_name ]['args'] = 1;
   1396 			}
   1397 
   1398 			if ( ! isset( self::$fields[ $opt_name ] ) ) {
   1399 				self::$fields[ $opt_name ]             = array();
   1400 				self::$priority[ $opt_name ]['fields'] = 1;
   1401 			}
   1402 
   1403 			if ( ! isset( self::$help[ $opt_name ] ) ) {
   1404 				self::$help[ $opt_name ]             = array();
   1405 				self::$priority[ $opt_name ]['help'] = 1;
   1406 			}
   1407 
   1408 			if ( ! isset( self::$errors[ $opt_name ] ) ) {
   1409 				self::$errors[ $opt_name ] = array();
   1410 			}
   1411 
   1412 			if ( ! isset( self::$init[ $opt_name ] ) ) {
   1413 				self::$init[ $opt_name ] = false;
   1414 			}
   1415 		}
   1416 
   1417 		/**
   1418 		 * Retrieve metadata from a file. Based on WP Core's get_file_data function
   1419 		 *
   1420 		 * @param string $file Path to the file.
   1421 		 *
   1422 		 * @return string
   1423 		 * @since 2.1.1
   1424 		 */
   1425 		public static function get_file_version( string $file ): string {
   1426 			$data = get_file_data( $file, array( 'version' ), 'plugin' );
   1427 
   1428 			return $data[0];
   1429 		}
   1430 
   1431 		/**
   1432 		 * Verify extension class name.
   1433 		 *
   1434 		 * @param string $opt_name   Panel opt_name.
   1435 		 * @param string $name       extension name.
   1436 		 * @param string $class_file Extension class file.
   1437 		 */
   1438 		private static function check_extension_class_file( string $opt_name, string $name = '', string $class_file = '' ) {
   1439 			$instance = null;
   1440 
   1441 			if ( file_exists( $class_file ) ) {
   1442 				self::$uses_extensions[ $opt_name ] = self::$uses_extensions[ $opt_name ] ?? array();
   1443 
   1444 				if ( ! in_array( $name, self::$uses_extensions[ $opt_name ], true ) ) {
   1445 					self::$uses_extensions[ $opt_name ][] = $name;
   1446 				}
   1447 
   1448 				self::$extensions[ $name ] = self::$extensions[ $name ] ?? array();
   1449 
   1450 				$version = Redux_Helpers::get_template_version( $class_file );
   1451 
   1452 				if ( empty( $version ) && ! empty( $instance ) ) {
   1453 					if ( isset( $instance->version ) ) {
   1454 						$version = $instance->version;
   1455 					}
   1456 				}
   1457 				self::$extensions[ $name ][ $version ] = self::$extensions[ $name ][ $version ] ?? $class_file;
   1458 
   1459 				$new_name  = str_replace( '_', '-', $name );
   1460 				$api_check = str_replace(
   1461 					array(
   1462 						'extension_' . $name,
   1463 						'class-redux-extension-' . $new_name,
   1464 					),
   1465 					array(
   1466 						$name . '_api',
   1467 						'class-redux-' . $new_name . '-api',
   1468 					),
   1469 					$class_file
   1470 				);
   1471 
   1472 				if ( file_exists( $api_check ) && ! class_exists( 'Redux_' . ucfirst( $name ) ) ) {
   1473 					include_once $api_check;
   1474 				}
   1475 			}
   1476 		}
   1477 
   1478 		/**
   1479 		 * Deprecated Sets all extensions in path.
   1480 		 *
   1481 		 * @param string $opt_name Panel opt_name.
   1482 		 * @param string $path     Path to extension folder.
   1483 		 *
   1484 		 * @deprecated No longer using camelCase naming convention.
   1485 		 */
   1486 		public static function setExtensions( string $opt_name, string $path ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
   1487 			if ( '' !== $opt_name ) {
   1488 				Redux_Functions_Ex::record_caller( $opt_name );
   1489 			}
   1490 
   1491 			self::set_extensions( $opt_name, $path );
   1492 		}
   1493 
   1494 		/**
   1495 		 * Sets all extensions in path.
   1496 		 *
   1497 		 * @param string $opt_name Panel opt_name.
   1498 		 * @param string $path     Path to extension folder.
   1499 		 * @param bool   $force    Make extension reload.
   1500 		 */
   1501 		public static function set_extensions( string $opt_name, string $path, bool $force = false ) {
   1502 			if ( '' === $path || '' === $opt_name ) {
   1503 				return;
   1504 			}
   1505 
   1506 			if ( version_compare( PHP_VERSION, '5.5.0', '<' ) ) {
   1507 				include_once Redux_Core::$dir . 'inc/lib/array-column.php';
   1508 			}
   1509 
   1510 			self::check_opt_name( $opt_name );
   1511 
   1512 			Redux_Functions_Ex::record_caller( $opt_name );
   1513 
   1514 			if ( is_dir( $path ) ) {
   1515 				$path   = trailingslashit( $path );
   1516 				$folder = str_replace( '.php', '', basename( $path ) );
   1517 
   1518 				$folder_fix = str_replace( '_', '-', $folder );
   1519 
   1520 				$files = array(
   1521 					$path . 'extension_' . $folder . '.php',
   1522 					$path . 'class-redux-extension-' . $folder_fix . '.php',
   1523 				);
   1524 
   1525 				$ext_file = Redux_Functions::file_exists_ex( $files );
   1526 
   1527 				if ( $ext_file ) {
   1528 					self::check_extension_class_file( $opt_name, $folder, $ext_file );
   1529 				} else {
   1530 					$folders = scandir( $path, 1 );
   1531 
   1532 					foreach ( $folders as $folder ) {
   1533 						if ( '.' === $folder || '..' === $folder ) {
   1534 							continue;
   1535 						}
   1536 
   1537 						if ( is_dir( $path . $folder ) ) {
   1538 							self::set_extensions( $opt_name, $path . $folder );
   1539 						}
   1540 					}
   1541 				}
   1542 			} elseif ( file_exists( $path ) ) {
   1543 				$name = explode( 'extension_', basename( $path ) );
   1544 				if ( isset( $name[1] ) && ! empty( $name[1] ) ) {
   1545 					$name = str_replace( '.php', '', $name[1] );
   1546 					self::check_extension_class_file( $opt_name, $name, $path );
   1547 				}
   1548 			}
   1549 
   1550 			self::$extension_paths[ $opt_name ] = $path;
   1551 
   1552 			if ( true === $force ) {
   1553 				if ( isset( self::$uses_extensions[ $opt_name ] ) && ! empty( self::$uses_extensions[ $opt_name ] ) ) {
   1554 					$redux = self::instance( $opt_name );
   1555 
   1556 					if ( isset( $redux ) ) {
   1557 						self::load_extensions( $redux );
   1558 					}
   1559 				}
   1560 			}
   1561 		}
   1562 
   1563 		/**
   1564 		 * Retrieves all loaded extensions.
   1565 		 */
   1566 		private static function get_all_extension() {
   1567 			$redux = self::all_instances();
   1568 
   1569 			foreach ( $redux as $instance ) {
   1570 				if ( ! empty( self::$uses_extensions[ $instance['args']['opt_name'] ] ) ) {
   1571 					continue;
   1572 				}
   1573 				if ( ! empty( $instance['extensions'] ) ) {
   1574 					self::get_instance_extension( $instance['args']['opt_name'], $instance );
   1575 				}
   1576 			}
   1577 		}
   1578 
   1579 		/**
   1580 		 * Gets all loaded extension for the passed ReduxFramework instance.
   1581 		 *
   1582 		 * @param string      $opt_name Panel opt_name.
   1583 		 * @param object|null $instance ReduxFramework instance.
   1584 		 */
   1585 		public static function get_instance_extension( string $opt_name, $instance ) {
   1586 			if ( ! empty( self::$uses_extensions[ $opt_name ] ) || empty( $opt_name ) ) {
   1587 				return;
   1588 			}
   1589 
   1590 			if ( empty( $instance ) ) {
   1591 				$instance = self::instance( $opt_name );
   1592 			}
   1593 
   1594 			if ( empty( $instance ) || empty( $instance->extensions ) ) {
   1595 				return;
   1596 			}
   1597 
   1598 			foreach ( $instance->extensions as $name => $extension ) {
   1599 				if ( 'widget_areas' === $name ) {
   1600 					$new = new Redux_Widget_Areas( $instance );
   1601 				}
   1602 
   1603 				if ( isset( self::$uses_extensions[ $opt_name ][ $name ] ) ) {
   1604 					continue;
   1605 				}
   1606 
   1607 				if ( isset( $extension->extension_dir ) ) {
   1608 					self::set_extensions( $opt_name, str_replace( $name, '', $extension->extension_dir ) );
   1609 				} elseif ( isset( $extension->extension_dir ) ) {
   1610 					self::set_extensions( $opt_name, str_replace( $name, '', $extension->extension_dir ) );
   1611 				}
   1612 			}
   1613 		}
   1614 
   1615 		/**
   1616 		 * Deprecated Gets loaded extensions.
   1617 		 *
   1618 		 * @param string $opt_name Panel opt_name.
   1619 		 * @param string $key      Extension name.
   1620 		 *
   1621 		 * @return array|bool|mixed
   1622 		 * @deprecated No longer using camelCase naming convention.
   1623 		 */
   1624 		public static function getExtensions( string $opt_name = '', string $key = '' ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
   1625 			_deprecated_function( __CLASS__ . '::' . __FUNCTION__, 'Redux 4.0.0', 'self::get_extensions( $opt_name, $key )' );
   1626 
   1627 			return self::get_extensions( $opt_name, $key );
   1628 		}
   1629 
   1630 		/**
   1631 		 * Gets loaded extensions.
   1632 		 *
   1633 		 * @param string $opt_name Panel opt_name.
   1634 		 * @param string $key      Extension name.
   1635 		 *
   1636 		 * @return array|bool|mixed
   1637 		 */
   1638 		public static function get_extensions( string $opt_name = '', string $key = '' ) {
   1639 			if ( empty( $opt_name ) ) {
   1640 				self::get_all_extension();
   1641 
   1642 				if ( empty( $key ) ) {
   1643 					return self::$extension_paths;
   1644 				} else {
   1645 					if ( isset( self::$extension_paths[ $key ] ) ) {
   1646 						return self::$extension_paths[ $key ];
   1647 					}
   1648 				}
   1649 			} else {
   1650 				if ( empty( self::$uses_extensions[ $opt_name ] ) ) {
   1651 					self::get_instance_extension( $opt_name, null );
   1652 				}
   1653 
   1654 				if ( empty( self::$uses_extensions[ $opt_name ] ) ) {
   1655 					return false;
   1656 				}
   1657 
   1658 				$instance_extensions = array();
   1659 
   1660 				foreach ( self::$uses_extensions[ $opt_name ] as $extension ) {
   1661 					$class_file = end( self::$extensions[ $extension ] );
   1662 					$directory  = explode( DIRECTORY_SEPARATOR, $class_file );
   1663 					array_pop( $directory );
   1664 					$directory       = trailingslashit( join( DIRECTORY_SEPARATOR, $directory ) );
   1665 					$name            = str_replace( '.php', '', basename( $extension ) );
   1666 					$extension_class = 'Redux_Extension_' . $name;
   1667 					$the_data        = array(
   1668 						'path'    => $class_file,
   1669 						'dir'     => $directory,
   1670 						'class'   => $extension_class,
   1671 						'version' => Redux_Helpers::get_template_version( $class_file ),
   1672 					);
   1673 
   1674 					if ( is_dir( $the_data['dir'] . $extension ) ) {
   1675 						$test_path = trailingslashit( $the_data['dir'] . $extension );
   1676 						if ( file_exists( $test_path . 'field_' . str_replace( '-', '', $extension ) . '.php' ) ) {
   1677 							$the_data['field'] = $test_path . 'field_' . str_replace( '-', '', $extension ) . '.php';
   1678 						}
   1679 						// Old extensions!
   1680 						if ( file_exists( $test_path . str_replace( '-', '', $extension ) . '.php' ) ) {
   1681 							$the_data['field'] = $test_path . str_replace( '-', '', $extension ) . '.php';
   1682 						}
   1683 					}
   1684 					$instance_extensions[ $extension ] = $the_data;
   1685 				}
   1686 
   1687 				return $instance_extensions;
   1688 			}
   1689 
   1690 			return false;
   1691 		}
   1692 
   1693 		/**
   1694 		 * Method to disables Redux demo mode popup.
   1695 		 */
   1696 		public static function disable_demo() {
   1697 			add_action( 'ReduxFrameworkPlugin_admin_notice', 'Redux::remove_demo' );
   1698 			add_action( 'redux_framework_plugin_admin_notice', 'Redux::remove_demo' );
   1699 		}
   1700 
   1701 		/**
   1702 		 * Callback used by self::disable_demo() to remove the demo mode notice from Redux.
   1703 		 */
   1704 		public static function remove_demo() {
   1705 			update_option( 'ReduxFrameworkPlugin_ACTIVATED_NOTICES', '' );
   1706 		}
   1707 
   1708 		/**
   1709 		 * Function which forces a panel/page to render.
   1710 		 *
   1711 		 * @param string|object $redux Panel opt_name or Redux object.
   1712 		 */
   1713 		public static function render( $redux = '' ) {
   1714 			if ( is_string( $redux ) ) {
   1715 				$redux = Redux_Instances::get_instance( $redux );
   1716 				if ( empty( $redux ) ) {
   1717 					return;
   1718 				}
   1719 			}
   1720 			$enqueue = new Redux_Enqueue( $redux );
   1721 			$enqueue->init();
   1722 			$panel = new \Redux_Panel( $redux );
   1723 			$panel->init();
   1724 		}
   1725 	}
   1726 
   1727 	Redux::load();
   1728 }