balmet.com

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

class-redux-options-constructor.php (33110B)


      1 <?php
      2 /**
      3  * Redux Options Class
      4  *
      5  * @class Redux_Options
      6  * @version 3.0.0
      7  * @package Redux Framework/Classes
      8  */
      9 
     10 defined( 'ABSPATH' ) || exit;
     11 
     12 if ( ! class_exists( 'Redux_Options_Constructor', false ) ) {
     13 
     14 	/**
     15 	 * Class Redux_Options
     16 	 */
     17 	class Redux_Options_Constructor extends Redux_Class {
     18 
     19 		/**
     20 		 * Array to hold single panel data.
     21 		 *
     22 		 * @var array
     23 		 */
     24 		public $no_panel = array();
     25 
     26 		/**
     27 		 * Array to hold single panel sections.
     28 		 *
     29 		 * @var array
     30 		 */
     31 		private $no_panel_section = array();
     32 
     33 		/**
     34 		 * Array to hold hidden fields.
     35 		 *
     36 		 * @var array
     37 		 */
     38 		private $hidden_perm_fields = array();
     39 
     40 		/**
     41 		 * Array to hold hidden sections.
     42 		 *
     43 		 * @var array
     44 		 */
     45 		public $hidden_perm_sections = array();
     46 
     47 		/**
     48 		 * Redux_Options constructor.
     49 		 *
     50 		 * @param object $parent ReduxFramework pointer.
     51 		 */
     52 		public function __construct( $parent ) {
     53 			parent::__construct( $parent );
     54 
     55 			add_action( 'admin_init', array( $this, 'register' ) );
     56 
     57 		}
     58 
     59 		/**
     60 		 * If we switch language in wpml the id of the post/page selected will be in the wrong language
     61 		 * So it won't appear as selected in the list of options and will be lost on next save, this fixes this by translating this id
     62 		 * Bonus it also gives the user the id of the post in the right language when they retrieve it
     63 		 * The recursion allows for it to work in a repeatable field.
     64 		 *
     65 		 * @param array $sections       Sections array.
     66 		 * @param array $options_values Values array.
     67 		 */
     68 		private function translate_data_field_recursive( array $sections, array &$options_values ) {
     69 			foreach ( $sections as $key => $section ) {
     70 				if ( 'fields' === $key ) {
     71 					foreach ( $section as $field ) {
     72 						if ( ! empty( $field['id'] ) && ! empty( $field['data'] ) && ! empty( $options_values[ $field['id'] ] ) && \Redux_Helpers::is_integer( $options_values[ $field['id'] ] ) ) {
     73 							$options_values[ $field['id'] ] = apply_filters( 'wpml_object_id', $options_values[ $field['id'] ], $field['data'], true );
     74 						}
     75 					}
     76 				} elseif ( is_array( $section ) && ! empty( $section ) ) {
     77 					$this->translate_data_field_recursive( $section, $options_values );
     78 				}
     79 			}
     80 		}
     81 
     82 		/**
     83 		 * Retrieves the options.
     84 		 */
     85 		public function get() {
     86 			$core = $this->core();
     87 
     88 			$defaults = false;
     89 
     90 			if ( ! empty( $core->defaults ) ) {
     91 				$defaults = $core->defaults;
     92 			}
     93 
     94 			if ( empty( $core->args ) ) {
     95 				return;
     96 			}
     97 
     98 			switch ( $core->args['database'] ) {
     99 				case 'transient':
    100 					$result = get_transient( $core->args['opt_name'] . '-transient' );
    101 					break;
    102 				case 'theme_mods':
    103 					$result = get_theme_mod( $core->args['opt_name'] . '-mods' );
    104 					break;
    105 				case 'theme_mods_expanded':
    106 					$result = get_theme_mods();
    107 					break;
    108 				case 'network':
    109 					$result = get_site_option( $core->args['opt_name'], array() );
    110 					break;
    111 				default:
    112 					$result = get_option( $core->args['opt_name'], array() );
    113 
    114 			}
    115 
    116 			if ( empty( $result ) && empty( $defaults ) ) {
    117 				return;
    118 			}
    119 
    120 			if ( empty( $result ) && ! empty( $defaults ) ) {
    121 				$results = $defaults;
    122 				$this->set( $results );
    123 			} else {
    124 				$core->options = $result;
    125 			}
    126 
    127 			// Don't iterate unnecessarily.
    128 			if ( has_filter( 'wpml_object_id' ) ) {
    129 				$this->translate_data_field_recursive( $core->sections, $core->options );
    130 			}
    131 
    132 			/**
    133 			 * Action 'redux/options/{opt_name}/options'
    134 			 *
    135 			 * @param mixed $value option values
    136 			 */
    137 
    138 			// phpcs:ignore WordPress.NamingConventions.ValidHookName
    139 			$core->options = apply_filters( "redux/options/{$core->args['opt_name']}/options", $core->options, $core->sections );
    140 
    141 			// Get transient values.
    142 			$core->transient_class->get();
    143 
    144 			// Set a global variable by the global_variable argument.
    145 			$this->set_global_variable( $core );
    146 		}
    147 
    148 		/**
    149 		 * ->set_options(); This is used to set an arbitrary option in the options array
    150 		 *
    151 		 * @since ReduxFramework 3.0.0
    152 		 *
    153 		 * @param string|array $value the value of the option being added.
    154 		 */
    155 		public function set( $value = '' ) {
    156 			$core = $this->core();
    157 
    158 			$core->transients['last_save'] = time();
    159 
    160 			if ( ! empty( $value ) ) {
    161 				$core->options = $value;
    162 
    163 				switch ( $core->args['database'] ) {
    164 					case 'transient':
    165 						set_transient( $core->args['opt_name'] . '-transient', $value, $core->args['transient_time'] );
    166 						break;
    167 					case 'theme_mods':
    168 						set_theme_mod( $core->args['opt_name'] . '-mods', $value );
    169 						break;
    170 					case 'theme_mods_expanded':
    171 						foreach ( $value as $k => $v ) {
    172 							set_theme_mod( $k, $v );
    173 						}
    174 						break;
    175 					case 'network':
    176 						update_site_option( $core->args['opt_name'], $value );
    177 						break;
    178 					default:
    179 						update_option( $core->args['opt_name'], $value );
    180 
    181 				}
    182 
    183 				// Store the changed values in the transient.
    184 				if ( $value !== $core->options ) {
    185 					foreach ( $value as $k => $v ) {
    186 						if ( ! isset( $core->options[ $k ] ) ) {
    187 							$core->options[ $k ] = '';
    188 						} elseif ( $v === $core->options[ $k ] ) {
    189 							unset( $core->options[ $k ] );
    190 						}
    191 					}
    192 
    193 					$core->transients['changed_values'] = $core->options;
    194 				}
    195 
    196 				$core->options = $value;
    197 
    198 				// Set a global variable by the global_variable argument.
    199 				$this->set_global_variable( $core );
    200 
    201 				// Saving the transient values.
    202 				$core->transient_class->set();
    203 			}
    204 		}
    205 
    206 		/**
    207 		 * Set a global variable by the global_variable argument
    208 		 *
    209 		 * @param object $core ReduxFramework core object.
    210 		 *
    211 		 * @return  void          (global was set)
    212 		 * @since   3.1.5
    213 		 */
    214 		private function set_global_variable( $core ): void {
    215 			if ( ! empty( $core->args['global_variable'] ) ) {
    216 				$options_global = $core->args['global_variable'];
    217 
    218 				/**
    219 				 * Filter 'redux/options/{opt_name}/global_variable'
    220 				 *
    221 				 * @param array $value option value to set global_variable with
    222 				 */
    223 
    224 				// phpcs:ignore WordPress.NamingConventions.ValidHookName
    225 				$GLOBALS[ $options_global ] = apply_filters( "redux/options/{$core->args['opt_name']}/global_variable", $core->options );
    226 
    227 				// Last save key.
    228 				if ( isset( $core->transients['last_save'] ) ) {
    229 					$GLOBALS[ $options_global ]['REDUX_LAST_SAVE'] = $core->transients['last_save'];
    230 				}
    231 
    232 				// Last compiler hook key.
    233 				if ( isset( $core->transients['last_compiler'] ) ) {
    234 					$GLOBALS[ $options_global ]['REDUX_LAST_COMPILER'] = $core->transients['last_compiler'];
    235 				}
    236 			}
    237 		}
    238 
    239 		/**
    240 		 * Register Option for use
    241 		 *
    242 		 * @since       1.0.0
    243 		 * @access      public
    244 		 * @return      void
    245 		 */
    246 		public function register() {
    247 			$core = $this->core();
    248 
    249 			if ( ! is_object( $core ) ) {
    250 				return;
    251 			}
    252 
    253 			if ( true === $core->args['options_api'] ) {
    254 				register_setting(
    255 					$core->args['opt_name'] . '_group',
    256 					$core->args['opt_name'],
    257 					array(
    258 						$this,
    259 						'validate_options',
    260 					)
    261 				);
    262 			}
    263 
    264 			if ( is_null( $core->sections ) ) {
    265 				return;
    266 			}
    267 
    268 			if ( empty( $core->options_defaults ) ) {
    269 				$core->options_defaults = $core->_default_values();
    270 			}
    271 
    272 			$run_update = false;
    273 
    274 			foreach ( $core->sections as $k => $section ) {
    275 				if ( isset( $section['type'] ) && 'divide' === $section['type'] ) {
    276 					continue;
    277 				}
    278 
    279 				$display = true;
    280 
    281 				if ( isset( $_GET['page'] ) && $_GET['page'] === $core->args['page_slug'] ) { // phpcs:ignore WordPress.Security.NonceVerification
    282 					if ( isset( $section['panel'] ) && false === $section['panel'] ) {
    283 						$display = false;
    284 					}
    285 				}
    286 
    287 				/**
    288 				 * Filter 'redux/options/{opt_name}/section/{section.id}'
    289 				 *
    290 				 * @param array $section section configuration
    291 				 */
    292 				if ( isset( $section['id'] ) ) {
    293 					// phpcs:ignore WordPress.NamingConventions.ValidHookName
    294 					$section = apply_filters( "redux/options/{$core->args['opt_name']}/section/{$section['id']}", $section );
    295 				}
    296 
    297 				if ( empty( $section ) ) {
    298 					unset( $core->sections[ $k ] );
    299 					continue;
    300 				}
    301 
    302 				if ( ! isset( $section['title'] ) ) {
    303 					$section['title'] = '';
    304 				}
    305 
    306 				if ( isset( $section['customizer_only'] ) && true === $section['customizer_only'] ) {
    307 					$section['panel']     = false;
    308 					$core->sections[ $k ] = $section;
    309 				}
    310 
    311 				$heading = $section['heading'] ?? $section['title'];
    312 
    313 				if ( isset( $section['permissions'] ) && false !== $section['permissions'] ) {
    314 					if ( ! Redux_Helpers::current_user_can( $section['permissions'] ) ) {
    315 						$core->hidden_perm_sections[] = $section['title'];
    316 
    317 						foreach ( $section['fields'] as $num => $field_data ) {
    318 							$field_type = $field_data['type'];
    319 
    320 							if ( 'section' !== $field_type || 'divide' !== $field_type || 'info' !== $field_type || 'raw' !== $field_type ) {
    321 								$field_id = $field_data['id'];
    322 								$default  = $core->options_defaults[ $field_id ] ?? '';
    323 								$data     = $core->options[ $field_id ] ?? $default;
    324 
    325 								$this->hidden_perm_fields[ $field_id ] = $data;
    326 							}
    327 						}
    328 
    329 						continue;
    330 					}
    331 				}
    332 
    333 				if ( ! $display || ! function_exists( 'add_settings_section' ) ) {
    334 					$this->no_panel_section[ $k ] = $section;
    335 				} else {
    336 					add_settings_section(
    337 						$core->args['opt_name'] . $k . '_section',
    338 						$heading,
    339 						array(
    340 							$core->render_class,
    341 							'section_desc',
    342 						),
    343 						$core->args['opt_name'] . $k . '_section_group'
    344 					);
    345 				}
    346 
    347 				$section_ident = false;
    348 				if ( isset( $section['fields'] ) ) {
    349 					foreach ( $section['fields'] as $fieldk => $field ) {
    350 						if ( ! isset( $field['type'] ) ) {
    351 							continue; // You need a type!
    352 						}
    353 
    354 						if ( 'info' === $field['type'] && isset( $field['raw_html'] ) && true === $field['raw_html'] ) {
    355 							$field['type']                             = 'raw';
    356 							$field['content']                          = $field['desc'];
    357 							$field['desc']                             = '';
    358 							$core->sections[ $k ]['fields'][ $fieldk ] = $field;
    359 						} elseif ( 'info' === $field['type'] ) {
    360 							if ( ! isset( $field['full_width'] ) ) {
    361 								$field['full_width']                       = true;
    362 								$core->sections[ $k ]['fields'][ $fieldk ] = $field;
    363 							}
    364 						}
    365 
    366 						if ( 'raw' === $field['type'] ) {
    367 							if ( isset( $field['align'] ) ) {
    368 								$field['full_width'] = ! $field['align'];
    369 								unset( $field['align'] );
    370 							} elseif ( ! isset( $field['full_width'] ) ) {
    371 								$field['full_width'] = true;
    372 							}
    373 							$core->sections[ $k ]['fields'][ $fieldk ] = $field;
    374 						}
    375 
    376 						/**
    377 						 * Filter 'redux/options/{opt_name}/field/{field.id}'
    378 						 *
    379 						 * @param array $field field config
    380 						 */
    381 
    382 						// phpcs:ignore WordPress.NamingConventions.ValidHookName
    383 						$field = apply_filters( "redux/options/{$core->args['opt_name']}/field/{$field['id']}/register", $field );
    384 
    385 						$core->field_types[ $field['type'] ] = $core->field_types[ $field['type'] ] ?? array();
    386 
    387 						$core->field_sections[ $field['type'] ][ $field['id'] ] = $k;
    388 
    389 						$display = true;
    390 
    391 						if ( isset( $_GET['page'] ) && $core->args['page_slug'] === $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification
    392 							if ( isset( $field['panel'] ) && false === $field['panel'] ) {
    393 								$display = false;
    394 							}
    395 						}
    396 						if ( isset( $field['customizer_only'] ) && true === $field['customizer_only'] ) {
    397 							$display = false;
    398 						}
    399 
    400 						if ( isset( $section['customizer'] ) ) {
    401 							$field['customizer']                       = $section['customizer'];
    402 							$core->sections[ $k ]['fields'][ $fieldk ] = $field;
    403 						}
    404 
    405 						if ( isset( $field['permissions'] ) && false !== $field['permissions'] ) {
    406 							if ( ! Redux_Helpers::current_user_can( $field['permissions'] ) ) {
    407 								$data = $core->options[ $field['id'] ] ?? $core->options_defaults[ $field['id'] ];
    408 
    409 								$this->hidden_perm_fields[ $field['id'] ] = $data;
    410 
    411 								continue;
    412 							}
    413 						}
    414 
    415 						if ( ! isset( $field['id'] ) ) {
    416 							echo '<br /><h3>No field ID is set.</h3><pre>';
    417 
    418 							// phpcs:ignore WordPress.PHP.DevelopmentFunctions
    419 							print_r( $field );
    420 
    421 							echo '</pre><br />';
    422 
    423 							continue;
    424 						}
    425 
    426 						if ( isset( $field['type'] ) && 'section' === $field['type'] ) {
    427 							if ( isset( $field['indent'] ) && true === $field['indent'] ) {
    428 								$section_ident = true;
    429 							} else {
    430 								$section_ident = false;
    431 							}
    432 						}
    433 
    434 						if ( isset( $field['type'] ) && 'info' === $field['type'] && $section_ident ) {
    435 							$field['indent'] = true;
    436 						}
    437 
    438 						$th = $core->render_class->get_header_html( $field );
    439 
    440 						$field['name'] = $core->args['opt_name'] . '[' . $field['id'] . ']';
    441 
    442 						// Set the default value if present.
    443 						$core->options_defaults[ $field['id'] ] = $core->options_defaults[ $field['id'] ] ?? '';
    444 
    445 						// Set the defaults to the value if not present.
    446 						$do_update = false;
    447 
    448 						// Check fields for values in the default parameter.
    449 						if ( ! isset( $core->options[ $field['id'] ] ) && isset( $field['default'] ) ) {
    450 							$core->options_defaults[ $field['id'] ] = $field['default'];
    451 							$core->options[ $field['id'] ]          = $field['default'];
    452 							$do_update                              = true;
    453 
    454 							// Check fields that hae no default value, but an options value with settings to
    455 							// be saved by default.
    456 						} elseif ( ! isset( $core->options[ $field['id'] ] ) && isset( $field['options'] ) ) {
    457 
    458 							// If sorter field, check for options and save them as defaults.
    459 							if ( 'sorter' === $field['type'] || 'sortable' === $field['type'] ) {
    460 								$core->options_defaults[ $field['id'] ] = $field['options'];
    461 								$core->options[ $field['id'] ]          = $field['options'];
    462 								$do_update                              = true;
    463 							}
    464 						}
    465 
    466 						// CORRECT URLS if media URLs are wrong, but attachment IDs are present.
    467 						if ( 'media' === $field['type'] ) {
    468 							if ( isset( $core->options[ $field['id'] ]['id'] ) && isset( $core->options[ $field['id'] ]['url'] ) && ! empty( $core->options[ $field['id'] ]['url'] ) && strpos( $core->options[ $field['id'] ]['url'], str_replace( 'http://', '', WP_CONTENT_URL ) ) === false ) {
    469 								$data = wp_get_attachment_url( $core->options[ $field['id'] ]['id'] );
    470 
    471 								if ( isset( $data ) && ! empty( $data ) ) {
    472 									$core->options[ $field['id'] ]['url'] = $data;
    473 
    474 									$data = wp_get_attachment_image_src(
    475 										$core->options[ $field['id'] ]['id'],
    476 										array(
    477 											150,
    478 											150,
    479 										)
    480 									);
    481 
    482 									$core->options[ $field['id'] ]['thumbnail'] = $data[0];
    483 									$do_update                                  = true;
    484 								}
    485 							}
    486 						}
    487 
    488 						if ( 'background' === $field['type'] ) {
    489 							if ( isset( $core->options[ $field['id'] ]['media']['id'] ) && isset( $core->options[ $field['id'] ]['background-image'] ) && ! empty( $core->options[ $field['id'] ]['background-image'] ) && strpos( $core->options[ $field['id'] ]['background-image'], str_replace( array( 'http://', 'https://' ), '', WP_CONTENT_URL ) ) === false ) {
    490 								$data = wp_get_attachment_url( $core->options[ $field['id'] ]['media']['id'] );
    491 
    492 								if ( isset( $data ) && ! empty( $data ) ) {
    493 									$core->options[ $field['id'] ]['background-image'] = $data;
    494 
    495 									$data = wp_get_attachment_image_src(
    496 										$core->options[ $field['id'] ]['media']['id'],
    497 										array(
    498 											150,
    499 											150,
    500 										)
    501 									);
    502 
    503 									$core->options[ $field['id'] ]['media']['thumbnail'] = $data[0];
    504 									$do_update = true;
    505 								}
    506 							}
    507 						}
    508 
    509 						if ( 'slides' === $field['type'] ) {
    510 							if ( isset( $core->options[ $field['id'] ] ) && is_array( $core->options[ $field['id'] ] ) && isset( $core->options[ $field['id'] ][0]['attachment_id'] ) && isset( $core->options[ $field['id'] ][0]['image'] ) && ! empty( $core->options[ $field['id'] ][0]['image'] ) && strpos( $core->options[ $field['id'] ][0]['image'], str_replace( array( 'http://', 'https://' ), '', WP_CONTENT_URL ) ) === false ) {
    511 								foreach ( $core->options[ $field['id'] ] as $key => $val ) {
    512 									$data = wp_get_attachment_url( $val['attachment_id'] );
    513 
    514 									if ( isset( $data ) && ! empty( $data ) ) {
    515 										$core->options[ $field['id'] ][ $key ]['image'] = $data;
    516 
    517 										$data = wp_get_attachment_image_src(
    518 											$val['attachment_id'],
    519 											array(
    520 												150,
    521 												150,
    522 											)
    523 										);
    524 
    525 										$core->options[ $field['id'] ][ $key ]['thumb'] = $data[0];
    526 										$do_update                                      = true;
    527 									}
    528 								}
    529 							}
    530 						}
    531 						// END -> CORRECT URLS if media URLs are wrong, but attachment IDs are present.
    532 						if ( true === $do_update && ! isset( $core->never_save_to_db ) ) {
    533 							if ( $core->args['save_defaults'] ) { // Only save that to the DB if allowed to.
    534 								$run_update = true;
    535 							}
    536 						}
    537 
    538 						if ( ! isset( $field['class'] ) ) { // No errors please.
    539 							$field['class'] = '';
    540 						}
    541 						$id = $field['id'];
    542 
    543 						/**
    544 						 * Filter 'redux/options/{opt_name}/field/{field.id}'.
    545 						 *
    546 						 * @param array $field field config
    547 						 */
    548 
    549 						// phpcs:ignore WordPress.NamingConventions.ValidHookName
    550 						$field = apply_filters( "redux/options/{$core->args['opt_name']}/field/{$field['id']}", $field );
    551 
    552 						if ( empty( $field ) || ! $field ) {
    553 							unset( $core->sections[ $k ]['fields'][ $fieldk ] );
    554 							continue;
    555 						}
    556 
    557 						if ( ! empty( $core->folds[ $field['id'] ]['parent'] ) ) { // This has some fold items, hide it by default.
    558 							$field['class'] .= ' fold';
    559 						}
    560 
    561 						if ( ! empty( $core->folds[ $field['id'] ]['children'] ) ) { // Sets the values you shoe fold children on.
    562 							$field['class'] .= ' fold-parent';
    563 						}
    564 
    565 						if ( ! empty( $field['compiler'] ) ) {
    566 							$field['class']                       .= ' compiler';
    567 							$core->compiler_fields[ $field['id'] ] = 1;
    568 						}
    569 
    570 						if ( isset( $field['unit'] ) && ! isset( $field['units'] ) ) {
    571 							$field['units'] = $field['unit'];
    572 							unset( $field['unit'] );
    573 						}
    574 
    575 						$core->sections[ $k ]['fields'][ $fieldk ] = $field;
    576 
    577 						if ( isset( $core->args['display_source'] ) ) {
    578 							// phpcs:ignore WordPress.PHP.DevelopmentFunctions
    579 							$th .= '<div id="' . $field['id'] . '-settings" style="display:none;"><pre>' . var_export( $core->sections[ $k ]['fields'][ $fieldk ], true ) . '</pre></div>';
    580 							$th .= '<br /><a href="#TB_inline?width=600&height=800&inlineId=' . $field['id'] . '-settings" class="thickbox"><small>View Source</small></a>';
    581 						}
    582 
    583 						/**
    584 						 * Action 'redux/options/{opt_name}/field/{field.type}/register'
    585 						 */
    586 
    587 						// phpcs:ignore WordPress.NamingConventions.ValidHookName
    588 						do_action( "redux/options/{$core->args['opt_name']}/field/{$field['type']}/register", $field );
    589 
    590 						$core->required_class->check_dependencies( $field );
    591 						$core->field_head[ $field['id'] ] = $th;
    592 
    593 						if ( ! $display || isset( $this->no_panel_section[ $k ] ) ) {
    594 							$this->no_panel[] = $field['id'];
    595 						} else {
    596 							if ( isset( $field['disabled'] ) && $field['disabled'] ) {
    597 								$field['label_for'] = 'redux_disable_field';
    598 							}
    599 
    600 							if ( isset( $field['hidden'] ) && $field['hidden'] ) {
    601 								$field['label_for'] = 'redux_hide_field';
    602 							}
    603 
    604 							if ( true === $core->args['options_api'] ) {
    605 								add_settings_field(
    606 									"{$fieldk}_field",
    607 									$th,
    608 									array(
    609 										$core->render_class,
    610 										'field_input',
    611 									),
    612 									"{$core->args['opt_name']}{$k}_section_group",
    613 									"{$core->args['opt_name']}{$k}_section",
    614 									$field
    615 								);
    616 							}
    617 						}
    618 					}
    619 				}
    620 			}
    621 
    622 			/**
    623 			 * Action 'redux/options/{opt_name}/register'
    624 			 *
    625 			 * @param array option sections
    626 			 */
    627 
    628 			// phpcs:ignore WordPress.NamingConventions.ValidHookName
    629 			do_action( "redux/options/{$core->args['opt_name']}/register", $core->sections );
    630 
    631 			if ( $run_update && ! isset( $core->never_save_to_db ) ) { // Always update the DB with new fields.
    632 				$this->set( $core->options );
    633 			}
    634 
    635 			if ( isset( $core->transients['run_compiler'] ) && $core->transients['run_compiler'] ) {
    636 
    637 				$core->no_output = true;
    638 				$temp            = $core->args['output_variables_prefix'];
    639 				// Allow the override of variable's prefix for use by SCSS or LESS.
    640 				if ( isset( $core->args['compiler_output_variables_prefix'] ) ) {
    641 					$core->args['output_variables_prefix'] = $core->args['compiler_output_variables_prefix'];
    642 				}
    643 				$core->output_class->enqueue();
    644 				$core->args['output_variables_prefix'] = $temp;
    645 
    646 				/**
    647 				 * Action 'redux/options/{opt_name}/compiler'
    648 				 *
    649 				 * @param array  options
    650 				 * @param string CSS that get sent to the compiler hook
    651 				 */
    652 
    653 				// phpcs:ignore WordPress.NamingConventions.ValidVariableName
    654 				$compiler_css = $core->compilerCSS;
    655 
    656 				// phpcs:ignore WordPress.NamingConventions.ValidHookName
    657 				do_action( "redux/options/{$core->args['opt_name']}/compiler", $core->options, $compiler_css, $core->transients['changed_values'], $core->output_variables );
    658 
    659 				/**
    660 				 * Action 'redux/options/{opt_name}/compiler/advanced'
    661 				 *
    662 				 * @param array  options
    663 				 * @param string CSS that get sent to the compiler hook, which sends the full Redux object
    664 				 */
    665 
    666 				// phpcs:ignore WordPress.NamingConventions.ValidHookName
    667 				do_action( "redux/options/{$core->args['opt_name']}/compiler/advanced", $core );
    668 
    669 				unset( $core->transients['run_compiler'] );
    670 				$core->transient_class->set();
    671 			}
    672 		}
    673 
    674 		/**
    675 		 * Get default options into an array suitable for the settings API
    676 		 *
    677 		 * @since       1.0.0
    678 		 * @access      public
    679 		 * @return      array $this->options_defaults
    680 		 */
    681 		public function default_values(): array {
    682 			$core = $this->core();
    683 
    684 			if ( ! is_null( $core->sections ) && is_null( $core->options_defaults ) ) {
    685 				$core->options_defaults = $core->options_defaults_class->default_values( $core->args['opt_name'], $core->sections, $core->wordpress_data );
    686 			}
    687 
    688 			/**
    689 			 * Filter 'redux/options/{opt_name}/defaults'
    690 			 *
    691 			 * @param array $defaults option default values
    692 			 */
    693 
    694 			$core->transients['changed_values'] = $core->transients['changed_values'] ?? array();
    695 
    696 			// phpcs:ignore WordPress.NamingConventions.ValidHookName
    697 			$core->options_defaults = apply_filters( "redux/options/{$core->args['opt_name']}/defaults", $core->options_defaults, $core->transients['changed_values'] );
    698 
    699 			return $core->options_defaults;
    700 		}
    701 
    702 		/**
    703 		 * Validate the Options before insertion
    704 		 *
    705 		 * @param       array $plugin_options The options array.
    706 		 *
    707 		 * @return array|mixed|string
    708 		 * @since       3.0.0
    709 		 * @access      public
    710 		 */
    711 		public function validate_options( array $plugin_options ) {
    712 			$core = $this->core();
    713 
    714 			if ( isset( $core->validation_ran ) ) {
    715 				return $plugin_options;
    716 			}
    717 
    718 			$core->validation_ran = 1;
    719 
    720 			// Save the values not in the panel.
    721 			if ( isset( $plugin_options['redux-no_panel'] ) ) {
    722 				$keys = explode( '|', $plugin_options['redux-no_panel'] );
    723 				foreach ( $keys as $key ) {
    724 					$plugin_options[ $key ] = $core->options[ $key ];
    725 				}
    726 				if ( isset( $plugin_options['redux-no_panel'] ) ) {
    727 					unset( $plugin_options['redux-no_panel'] );
    728 				}
    729 			}
    730 
    731 			if ( is_array( $this->hidden_perm_fields ) && ! empty( $this->hidden_perm_fields ) ) {
    732 				foreach ( $this->hidden_perm_fields as $id => $data ) {
    733 					$plugin_options[ $id ] = $data;
    734 				}
    735 			}
    736 
    737 			if ( $plugin_options === $core->options ) {
    738 				return $plugin_options;
    739 			}
    740 
    741 			$time = time();
    742 
    743 			// Sets last saved time.
    744 			$core->transients['last_save'] = $time;
    745 
    746 			$imported_options = array();
    747 
    748 			if ( isset( $plugin_options['import_link'] ) && '' !== $plugin_options['import_link'] && ! ! wp_http_validate_url( $plugin_options['import_link'] ) ) {
    749 				$import           = wp_remote_retrieve_body( wp_remote_get( $plugin_options['import_link'] ) );
    750 				$imported_options = json_decode( $import, true );
    751 			}
    752 			if ( isset( $plugin_options['import_code'] ) && '' !== $plugin_options['import_code'] ) {
    753 				$imported_options = json_decode( $plugin_options['import_code'], true );
    754 			}
    755 
    756 			// Import.
    757 			$core->transients['last_save_mode'] = 'import'; // Last save mode.
    758 			$core->transients['last_compiler']  = $time;
    759 			$core->transients['last_import']    = $time;
    760 			$core->transients['run_compiler']   = 1;
    761 
    762 			if ( is_array( $imported_options ) && ! empty( $imported_options ) && isset( $imported_options['redux-backup'] ) && ( 1 === $imported_options['redux-backup'] || '1' === $imported_options['redux-backup'] ) ) {
    763 				$core->transients['changed_values'] = array();
    764 				foreach ( $plugin_options as $key => $value ) {
    765 					if ( isset( $imported_options[ $key ] ) && $value !== $imported_options[ $key ] ) {
    766 						$plugin_options[ $key ]                     = $value;
    767 						$core->transients['changed_values'][ $key ] = $value;
    768 					}
    769 				}
    770 
    771 				/**
    772 				 * Action 'redux/options/{opt_name}/import'.
    773 				 *
    774 				 * @param  &array [&$plugin_options, redux_options]
    775 				 */
    776 
    777 				// phpcs:ignore WordPress.NamingConventions.ValidHookName
    778 				do_action_ref_array(
    779 					"redux/options/{$core->args['opt_name']}/import", // phpcs:ignore WordPress.NamingConventions.ValidHookName
    780 					array(
    781 						&$plugin_options,
    782 						$imported_options,
    783 						$core->transients['changed_values'],
    784 					)
    785 				);
    786 
    787 				setcookie( 'redux_current_tab_' . $core->args['opt_name'], '', 1, '/', $time + 1000, '/' );
    788 				$_COOKIE[ 'redux_current_tab_' . $core->args['opt_name'] ] = 1;
    789 
    790 				unset( $plugin_options['defaults'], $plugin_options['compiler'], $plugin_options['import'], $plugin_options['import_code'] );
    791 				if ( in_array( $core->args['database'], array( 'transient', 'theme_mods', 'theme_mods_expanded', 'network' ), true ) ) {
    792 					$this->set( $plugin_options );
    793 
    794 					return;
    795 				}
    796 
    797 				$plugin_options = wp_parse_args( $imported_options, $plugin_options );
    798 
    799 				$core->transient_class->set();
    800 
    801 				return $plugin_options;
    802 			}
    803 
    804 			// Reset all to defaults.
    805 			if ( ! empty( $plugin_options['defaults'] ) ) {
    806 				if ( empty( $core->options_defaults ) ) {
    807 					$core->options_defaults = $core->_default_values();
    808 				}
    809 
    810 				/**
    811 				 * Filter: 'redux/validate/{opt_name}/defaults'.
    812 				 *
    813 				 * @param  &array [ $this->options_defaults, $plugin_options]
    814 				 */
    815 
    816 				// phpcs:ignore WordPress.NamingConventions.ValidHookName
    817 				$plugin_options = apply_filters( "redux/validate/{$core->args['opt_name']}/defaults", $core->options_defaults );
    818 
    819 				$core->transients['changed_values'] = array();
    820 
    821 				if ( empty( $core->options ) ) {
    822 					$core->options = $core->options_defaults;
    823 				}
    824 
    825 				foreach ( $core->options as $key => $value ) {
    826 					if ( isset( $plugin_options[ $key ] ) && $plugin_options[ $key ] !== $value ) {
    827 						$core->transients['changed_values'][ $key ] = $value;
    828 					}
    829 				}
    830 
    831 				$core->transients['run_compiler']   = 1;
    832 				$core->transients['last_save_mode'] = 'defaults'; // Last save mode.
    833 
    834 				$core->transient_class->set();
    835 
    836 				return $plugin_options;
    837 			}
    838 
    839 			// Section reset to defaults.
    840 			if ( ! empty( $plugin_options['defaults-section'] ) ) {
    841 				if ( isset( $plugin_options['redux-section'] ) && isset( $core->sections[ $plugin_options['redux-section'] ]['fields'] ) ) {
    842 					if ( empty( $core->options_defaults ) ) {
    843 						$core->options_defaults = $core->_default_values();
    844 					}
    845 
    846 					foreach ( $core->sections[ $plugin_options['redux-section'] ]['fields'] as $field ) {
    847 						if ( isset( $core->options_defaults[ $field['id'] ] ) ) {
    848 							$plugin_options[ $field['id'] ] = $core->options_defaults[ $field['id'] ];
    849 						} else {
    850 							$plugin_options[ $field['id'] ] = '';
    851 						}
    852 
    853 						if ( isset( $field['compiler'] ) ) {
    854 							$compiler = true;
    855 						}
    856 					}
    857 
    858 					/**
    859 					 * Filter: 'redux/validate/{opt_name}/defaults_section'.
    860 					 *
    861 					 * @param  &array [ $this->options_defaults, $plugin_options]
    862 					 */
    863 
    864 					// phpcs:ignore WordPress.NamingConventions.ValidHookName
    865 					$plugin_options = apply_filters( "redux/validate/{$core->args['opt_name']}/defaults_section", $plugin_options );
    866 				}
    867 
    868 				$core->transients['changed_values'] = array();
    869 				foreach ( $core->options as $key => $value ) {
    870 					if ( isset( $plugin_options[ $key ] ) && $plugin_options[ $key ] !== $value ) {
    871 						$core->transients['changed_values'][ $key ] = $value;
    872 					}
    873 				}
    874 
    875 				if ( isset( $compiler ) ) {
    876 					$core->transients['last_compiler'] = $time;
    877 					$core->transients['run_compiler']  = 1;
    878 				}
    879 
    880 				$core->transients['last_save_mode'] = 'defaults_section'; // Last save mode.
    881 
    882 				unset( $plugin_options['defaults'], $plugin_options['defaults_section'], $plugin_options['import'], $plugin_options['import_code'], $plugin_options['import_link'], $plugin_options['compiler'], $plugin_options['redux-section'] );
    883 
    884 				$core->transient_class->set();
    885 
    886 				return $plugin_options;
    887 			}
    888 
    889 			$core->transients['last_save_mode'] = 'normal'; // Last save mode.
    890 
    891 			/**
    892 			 * Filter: 'redux/validate/{opt_name}/before_validation'
    893 			 *
    894 			 * @param  &array [&$plugin_options, redux_options]
    895 			 */
    896 
    897 			// phpcs:ignore WordPress.NamingConventions.ValidHookName
    898 			$plugin_options = apply_filters( "redux/validate/{$core->args['opt_name']}/before_validation", $plugin_options, $core->options );
    899 
    900 			// Validate fields (if needed).
    901 			$plugin_options = $core->validate_class->validate( $plugin_options, $core->options, $core->sections );
    902 
    903 			// Sanitize options, if needed.
    904 			$plugin_options = $core->sanitize_class->sanitize( $plugin_options, $core->options, $core->sections );
    905 
    906 			if ( ! empty( $core->errors ) || ! empty( $core->warnings ) || ! empty( $core->sanitize ) ) {
    907 				$core->transients['notices'] = array(
    908 					'errors'   => $core->errors,
    909 					'warnings' => $core->warnings,
    910 					'sanitize' => $core->sanitize,
    911 				);
    912 			}
    913 
    914 			if ( ! isset( $core->transients['changed_values'] ) ) {
    915 				$core->transients['changed_values'] = array();
    916 			}
    917 
    918 			/**
    919 			 * Action 'redux/options/{opt_name}/validate'
    920 			 *
    921 			 * @param  &array [&$plugin_options, redux_options]
    922 			 */
    923 			// phpcs:ignore WordPress.NamingConventions.ValidHookName
    924 			do_action_ref_array(
    925 			// phpcs:ignore WordPress.NamingConventions.ValidHookName
    926 				"redux/options/{$core->args['opt_name']}/validate",
    927 				array(
    928 					&$plugin_options,
    929 					$core->options,
    930 					$core->transients['changed_values'],
    931 				)
    932 			);
    933 
    934 			if ( ! empty( $plugin_options['compiler'] ) ) {
    935 				unset( $plugin_options['compiler'] );
    936 
    937 				$core->transients['last_compiler'] = $time;
    938 				$core->transients['run_compiler']  = 1;
    939 			}
    940 
    941 			$core->transients['changed_values'] = array(); // Changed values since last save.
    942 
    943 			if ( ! empty( $core->options ) ) {
    944 				foreach ( $core->options as $key => $value ) {
    945 					if ( isset( $plugin_options[ $key ] ) && $plugin_options[ $key ] !== $value ) {
    946 						$core->transients['changed_values'][ $key ] = $value;
    947 					}
    948 				}
    949 			}
    950 
    951 			unset( $plugin_options['defaults'], $plugin_options['defaults_section'], $plugin_options['import'], $plugin_options['import_code'], $plugin_options['import_link'], $plugin_options['compiler'], $plugin_options['redux-section'] );
    952 			if ( in_array( $core->args['database'], array( 'transient', 'theme_mods', 'theme_mods_expanded' ), true ) ) {
    953 				$core->set( $core->args['opt_name'], $plugin_options );
    954 				return;
    955 			}
    956 
    957 			if ( defined( 'WP_CACHE' ) && WP_CACHE && class_exists( 'W3_ObjectCache' ) && function_exists( 'w3_instance' ) ) {
    958 				$w3_inst = w3_instance( 'W3_ObjectCache' );
    959 				$w3      = $w3_inst->instance();
    960 				$key     = $w3->_get_cache_key( $core->args['opt_name'] . '-transients', 'transient' );
    961 				$w3->delete( $key, 'transient', true );
    962 			}
    963 
    964 			$core->transient_class->set();
    965 
    966 			return $plugin_options;
    967 		}
    968 
    969 		/**
    970 		 * ->get_default(); This is used to return the default value if default_show is set.
    971 		 *
    972 		 * @param string $opt_name The option name to return.
    973 		 * @param mixed  $default  (null)  The value to return if default not set.
    974 		 *
    975 		 * @return      mixed $default
    976 		 * @since       1.0.1
    977 		 * @access      public
    978 		 */
    979 		public function get_default( string $opt_name, $default = null ) {
    980 			if ( true === $this->args['default_show'] ) {
    981 
    982 				if ( empty( $this->options_defaults ) ) {
    983 					$this->default_values(); // fill cache.
    984 				}
    985 
    986 				$default = array_key_exists( $opt_name, $this->options_defaults ) ? $this->options_defaults[ $opt_name ] : $default;
    987 			}
    988 
    989 			return $default;
    990 		}
    991 
    992 		/**
    993 		 * Get the default value for an option
    994 		 *
    995 		 * @param string $key       The option's ID.
    996 		 * @param string $array_key The key of the default's array.
    997 		 *
    998 		 * @return mixed
    999 		 * @since  3.3.6
   1000 		 * @access public
   1001 		 */
   1002 		public function get_default_value( string $key, $array_key = false ) {
   1003 			if ( empty( $this->options_defaults ) ) {
   1004 				$this->options_defaults = $this->default_values();
   1005 			}
   1006 
   1007 			$defaults = $this->options_defaults;
   1008 			$value    = '';
   1009 
   1010 			if ( isset( $defaults[ $key ] ) ) {
   1011 				if ( false !== $array_key && isset( $defaults[ $key ][ $array_key ] ) ) {
   1012 					$value = $defaults[ $key ][ $array_key ];
   1013 				} else {
   1014 					$value = $defaults[ $key ];
   1015 				}
   1016 			}
   1017 
   1018 			return $value;
   1019 		}
   1020 	}
   1021 }