Completed
Push — master ( 8e54f7...c272ee )
by
unknown
53s
created
redux-core/class-redux-core.php 1 patch
Indentation   +617 added lines, -617 removed lines patch added patch discarded remove patch
@@ -11,623 +11,623 @@
 block discarded – undo
11 11
 
12 12
 if ( ! class_exists( 'Redux_Core', false ) ) {
13 13
 
14
-	/**
15
-	 * Class Redux_Core
16
-	 */
17
-	class Redux_Core {
18
-
19
-		/**
20
-		 * Class instance.
21
-		 *
22
-		 * @var null|Redux_Core
23
-		 */
24
-		public static ?Redux_Core $instance = null;
25
-
26
-		/**
27
-		 * Project version
28
-		 *
29
-		 * @var string
30
-		 */
31
-		public static string $version;
32
-
33
-		/**
34
-		 * Project directory.
35
-		 *
36
-		 * @var string.
37
-		 */
38
-		public static string $dir;
39
-
40
-		/**
41
-		 * Project URL.
42
-		 *
43
-		 * @var string.
44
-		 */
45
-		public static string $url;
46
-
47
-		/**
48
-		 * Base directory path.
49
-		 *
50
-		 * @var string
51
-		 */
52
-		public static string $redux_path;
53
-
54
-		/**
55
-		 * Absolute direction path to WordPress upload directory.
56
-		 *
57
-		 * @var string
58
-		 */
59
-		public static string $upload_dir = '';
60
-
61
-		/**
62
-		 * Full URL to WordPress upload directory.
63
-		 *
64
-		 * @var null|string
65
-		 */
66
-		public static ?string $upload_url = '';
67
-
68
-		/**
69
-		 * Set when Redux is run as a plugin.
70
-		 *
71
-		 * @var bool
72
-		 */
73
-		public static bool $is_plugin = true;
74
-
75
-		/**
76
-		 * Indicated in_theme or in_plugin.
77
-		 *
78
-		 * @var string
79
-		 */
80
-		public static string $installed = '';
81
-
82
-		/**
83
-		 * Set when Redux is run as a plugin.
84
-		 *
85
-		 * @var bool
86
-		 */
87
-		public static bool $as_plugin = false;
88
-
89
-		/**
90
-		 * Set when Redux is embedded within a theme.
91
-		 *
92
-		 * @var bool
93
-		 */
94
-		public static bool $in_theme = false;
95
-
96
-		/**
97
-		 * Pointer to an updated Google fonts array.
98
-		 *
99
-		 * @var array|null
100
-		 */
101
-		public static ?array $updated_google_fonts = array();
102
-
103
-		/**
104
-		 * List of files calling Redux.
105
-		 *
106
-		 * @var array|null
107
-		 */
108
-		public static ?array $callers = array();
109
-
110
-		/**
111
-		 * Pointer to _SERVER global.
112
-		 *
113
-		 * @var array|null
114
-		 */
115
-		public static ?array $server = array();
116
-
117
-		/**
118
-		 * Field folding information for localization.
119
-		 *
120
-		 * @var null|array
121
-		 */
122
-		public static ?array $required = array();
123
-
124
-		/**
125
-		 * Field child-folding information for localization.
126
-		 *
127
-		 * @var null|array
128
-		 */
129
-		public static ?array $required_child = array();
130
-
131
-		/**
132
-		 * Array of fields to be folded.
133
-		 *
134
-		 * @var array|null
135
-		 */
136
-		public static ?array $folds = array();
137
-
138
-		/**
139
-		 * Array of fields that didn't pass the fold dependency test and are hidden.
140
-		 *
141
-		 * @var null|array
142
-		 */
143
-		public static ?array $fields_hidden = array();
144
-
145
-		/**
146
-		 * Values to generate google font CSS.
147
-		 *
148
-		 * @var null|array
149
-		 */
150
-		public static ?array $typography = array();
151
-
152
-		/**
153
-		 * Validation ran flag.
154
-		 *
155
-		 * @var bool
156
-		 */
157
-		public static bool $validation_ran = false;
158
-
159
-		/**
160
-		 * No output flag.
161
-		 *
162
-		 * @var bool
163
-		 */
164
-		public static bool $no_output = false;
165
-
166
-		/**
167
-		 * Array of fonts used by the panel for localization.
168
-		 *
169
-		 * @var null|array
170
-		 */
171
-		public static ?array $fonts = array();
172
-
173
-		/**
174
-		 * Array of Google fonts used by the panel for localization.
175
-		 *
176
-		 * @var null|array
177
-		 */
178
-		public static ?array $google_array = array();
179
-
180
-		/**
181
-		 * Array of various font groups used within the typography field.
182
-		 *
183
-		 * @var null|array
184
-		 */
185
-		public static ?array $font_groups = array();
186
-
187
-		/**
188
-		 * File system object used for I/O file operations.  Done the WordPress way.
189
-		 *
190
-		 * @var null|object
191
-		 */
192
-		public static ?object $filesystem;
193
-
194
-		/**
195
-		 * Pointer to the third party fixes class.
196
-		 *
197
-		 * @var Redux_ThirdParty_Fixes
198
-		 */
199
-		public static Redux_ThirdParty_Fixes $third_party_fixes;
200
-
201
-		/**
202
-		 * Redux Welcome screen object.
203
-		 *
204
-		 * @var Redux_Welcome
205
-		 */
206
-		public static Redux_Welcome $welcome;
207
-
208
-		/**
209
-		 * Creates instance of class.
210
-		 *
211
-		 * @return Redux_Core
212
-		 * @throws Exception Comment.
213
-		 */
214
-		public static function instance(): ?Redux_Core {
215
-			if ( ! self::$instance ) {
216
-				self::$instance = new self();
217
-
218
-				self::$instance->includes();
219
-				self::$instance->init();
220
-				self::$instance->hooks();
221
-
222
-				add_action( 'plugins_loaded', array( 'Redux_Core', 'plugins_loaded' ) );
223
-			}
224
-
225
-			return self::$instance;
226
-		}
227
-
228
-		/**
229
-		 * Things to run after pluggable.php had loaded.
230
-		 */
231
-		public static function plugins_loaded() {}
232
-
233
-		/**
234
-		 * Class init.
235
-		 */
236
-		private function init() {
237
-			self::$server = array(
238
-				'SERVER_SOFTWARE'      => '',
239
-				'REMOTE_ADDR'          => Redux_Helpers::is_local_host() ? '127.0.0.1' : '',
240
-				'HTTP_USER_AGENT'      => '',
241
-				'HTTP_HOST'            => '',
242
-				'REQUEST_URI'          => '',
243
-				'HTTP_X_FORWARDED_FOR' => '',
244
-			);
245
-
246
-			// phpcs:disable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
247
-			if ( ! empty( $_SERVER['SERVER_SOFTWARE'] ) ) {
248
-				self::$server['SERVER_SOFTWARE'] = sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) );
249
-			}
250
-			if ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) {
251
-				self::$server['REMOTE_ADDR'] = sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) );
252
-			}
253
-			if ( ! empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
254
-				self::$server['HTTP_USER_AGENT'] = sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) );
255
-			}
256
-			if ( ! empty( $_SERVER['HTTP_HOST'] ) ) {
257
-				self::$server['HTTP_HOST'] = sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) );
258
-			}
259
-			if ( ! empty( $_SERVER['REQUEST_URI'] ) ) {
260
-				self::$server['REQUEST_URI'] = sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) );
261
-			}
262
-			if ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
263
-				self::$server['HTTP_X_FORWARDED_FOR'] = sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_FORWARDED_FOR'] ) );
264
-			}
265
-			// phpcs:enable
266
-
267
-			self::$dir = trailingslashit( wp_normalize_path( dirname( realpath( __FILE__ ) ) ) );
268
-
269
-			Redux_Functions_Ex::generator();
270
-
271
-			if ( defined( 'REDUX_PLUGIN_FILE' ) ) {
272
-				$plugin_info = Redux_Functions_Ex::is_inside_plugin( REDUX_PLUGIN_FILE );
273
-			}
274
-
275
-			$plugin_info = Redux_Functions_Ex::is_inside_plugin( __FILE__ );
276
-
277
-			if ( false !== $plugin_info ) {
278
-				self::$installed = class_exists( 'Redux_Framework_Plugin' ) ? 'plugin' : 'in_plugin';
279
-				self::$is_plugin = class_exists( 'Redux_Framework_Plugin' );
280
-				self::$as_plugin = true;
281
-				self::$url       = trailingslashit( dirname( $plugin_info['url'] ) );
282
-			} else {
283
-				$theme_info = Redux_Functions_Ex::is_inside_theme( __FILE__ );
284
-				if ( false !== $theme_info ) {
285
-					self::$url       = trailingslashit( dirname( $theme_info['url'] ) );
286
-					self::$in_theme  = true;
287
-					self::$installed = 'in_theme';
288
-				}
289
-			}
290
-
291
-			// phpcs:ignore WordPress.NamingConventions.ValidHookName
292
-			self::$url = apply_filters( 'redux/url', self::$url );
293
-
294
-			// phpcs:ignore WordPress.NamingConventions.ValidHookName
295
-			self::$dir = apply_filters( 'redux/dir', self::$dir );
296
-
297
-			// phpcs:ignore WordPress.NamingConventions.ValidHookName
298
-			self::$is_plugin = apply_filters( 'redux/is_plugin', self::$is_plugin );
299
-
300
-			if ( ! function_exists( 'current_time' ) ) {
301
-				require_once ABSPATH . '/wp-includes/functions.php';
302
-			}
303
-
304
-			$upload_dir       = wp_upload_dir();
305
-			self::$upload_dir = $upload_dir['basedir'] . '/redux/';
306
-			self::$upload_url = str_replace( array( 'https://', 'http://' ), '//', $upload_dir['baseurl'] . '/redux/' );
307
-
308
-			// phpcs:ignore WordPress.NamingConventions.ValidHookName
309
-			self::$upload_dir = apply_filters( 'redux/upload_dir', self::$upload_dir );
310
-
311
-			// phpcs:ignore WordPress.NamingConventions.ValidHookName
312
-			self::$upload_url = apply_filters( 'redux/upload_url', self::$upload_url );
313
-		}
314
-
315
-		/**
316
-		 * Code to execute on a framework __construct.
317
-		 *
318
-		 * @param ReduxFramework $redux Pointer to ReduxFramework object.
319
-		 */
320
-		public static function core_construct( ReduxFramework $redux ) {
321
-			self::$third_party_fixes = new Redux_ThirdParty_Fixes( $redux );
322
-
323
-			Redux_ThemeCheck::get_instance();
324
-		}
325
-
326
-		/**
327
-		 * Autoregister run.
328
-		 *
329
-		 * @throws Exception Comment.
330
-		 */
331
-		private function includes() {
332
-			if ( is_admin() ) {
333
-				if ( class_exists( 'Redux_Pro' ) && isset( Redux_Pro::$dir ) ) {
334
-					echo '<div class="error"><p>' . sprintf( esc_html__( 'Redux has detected the Redux Pro plugin is enabled. All featured of Redux Pro are now part of the entire Redux plugin and is no longer required. Please disable the Redux Pro plugin to avoid potential conflicts.', 'redux-framework' ), '<code></code>' ) . '</p></div>';
335
-				}
336
-			}
337
-
338
-			require_once __DIR__ . '/inc/classes/class-redux-path.php';
339
-			require_once __DIR__ . '/inc/classes/class-redux-functions-ex.php';
340
-			require_once __DIR__ . '/inc/classes/class-redux-helpers.php';
341
-			require_once __DIR__ . '/inc/classes/class-redux-instances.php';
342
-
343
-			Redux_Functions_Ex::register_class_path( 'Redux', __DIR__ . '/inc/classes' );
344
-			Redux_Functions_Ex::register_class_path( 'Redux', __DIR__ . '/inc/welcome' );
345
-
346
-			spl_autoload_register( array( $this, 'register_classes' ) );
347
-
348
-			self::$welcome = new Redux_Welcome();
349
-
350
-			add_filter( 'debug_information', array( $this, 'add_debug_info' ) );
351
-		}
352
-
353
-		/**
354
-		 * Add debug info for the WP Site Health screen.
355
-		 *
356
-		 * @param array $debug_info Debug data.
357
-		 *
358
-		 * @return array
359
-		 * @throws ReflectionException Exception.
360
-		 */
361
-		public function add_debug_info( array $debug_info ): array {
362
-
363
-			// Get browser data.
364
-			if ( ! class_exists( 'ReduxBrowser' ) ) {
365
-				require_once self::$dir . 'inc/lib/browser.php';
366
-			}
367
-
368
-			$browser = new ReduxBrowser();
369
-
370
-			$browser_data = array(
371
-				'Agent'    => $browser->getUserAgent(),
372
-				'Browser'  => $browser->getBrowser(),
373
-				'Version'  => $browser->getVersion(),
374
-				'Platform' => $browser->getPlatform(),
375
-			);
376
-
377
-			// Set Redux dir permission results to Site Health screen.
378
-			$debug_info['wp-filesystem']['fields'][] = array(
379
-				'label' => esc_html__( 'The Redux upload directory', 'redux-framework' ),
380
-				'value' => wp_is_writable( self::$upload_dir ) ? 'Writable' : 'Not writable',
381
-			);
382
-
383
-			// Set Redux plugin results to Site Health screen.
384
-			$debug_info['redux-framework'] = array(
385
-				'label'       => esc_html__( 'Redux Framework', 'redux-framework' ),
386
-				'description' => esc_html__( 'Debug information specific to Redux Framework.', 'redux-framework' ),
387
-				'fields'      => array(
388
-					'version'        => array(
389
-						'label' => esc_html__( 'Version', 'redux-framework' ),
390
-						'value' => self::$version,
391
-					),
392
-					'installation'   => array(
393
-						'label' => esc_html__( 'Installation', 'redux-framework' ),
394
-						'value' => self::$installed,
395
-					),
396
-					'data directory' => array(
397
-						'label' => esc_html__( 'Data directory', 'redux-framework' ),
398
-						'value' => self::$dir,
399
-					),
400
-					'browser'        => array(
401
-						'label' => esc_html__( 'Browser', 'redux-framework' ),
402
-						'value' => $browser_data,
403
-					),
404
-				),
405
-			);
406
-
407
-			$redux = Redux::all_instances();
408
-
409
-			$extensions = array();
410
-
411
-			if ( ! empty( $redux ) && is_array( $redux ) ) {
412
-				foreach ( $redux as $inst => $data ) {
413
-					Redux::init( $inst );
414
-
415
-					$inst_name = ucwords( str_replace( array( '_', '-' ), ' ', $inst ) );
416
-					$args      = $data->args;
417
-
418
-					$ext = Redux::get_extensions( $inst );
419
-					if ( ! empty( $ext ) && is_array( $ext ) ) {
420
-						ksort( $ext );
421
-
422
-						foreach ( $ext as $name => $arr ) {
423
-							$ver = $arr['version'];
424
-
425
-							$ex = esc_html( ucwords( str_replace( array( '_', '-' ), ' ', $name ) ) );
426
-
427
-							$extensions[ $ex ] = esc_html( $ver );
428
-						}
429
-					}
430
-
431
-					// Output Redux instances.
432
-					$debug_info[ 'redux-instance-' . $inst ] = array(
433
-						// translators: %s = Instance name.
434
-						'label'       => sprintf( esc_html__( 'Redux Instance: %s', 'redux-framework' ), $inst_name ),
435
-						// translators: %s = Instance name w/ HTML.
436
-						'description' => sprintf( esc_html__( 'Debug information for the %s Redux instance.', 'redux-framework' ), '<code>' . $inst . '</code>' ),
437
-						'fields'      => array(
438
-							'opt_name'         => array(
439
-								'label' => esc_html( 'opt_name' ),
440
-								'value' => $args['opt_name'],
441
-							),
442
-							'global_variable'  => array(
443
-								'label' => esc_html( 'global_variable' ),
444
-								'value' => $args['global_variable'],
445
-							),
446
-							'dev_mode'         => array(
447
-								'label' => esc_html( 'dev_mode' ),
448
-								'value' => $args['dev_mode'] ? 'true' : 'false',
449
-							),
450
-							'ajax_save'        => array(
451
-								'label' => esc_html( 'ajax_save' ),
452
-								'value' => $args['ajax_save'] ? 'true' : 'false',
453
-							),
454
-							'page_slug'        => array(
455
-								'label' => esc_html( 'page_slug' ),
456
-								'value' => $args['page_slug'],
457
-							),
458
-							'page_permissions' => array(
459
-								'label' => esc_html( 'page_permissions' ),
460
-								'value' => $args['page_permissions'],
461
-							),
462
-							'menu_type'        => array(
463
-								'label' => esc_html( 'menu_type' ),
464
-								'value' => $args['menu_type'],
465
-							),
466
-							'page_parent'      => array(
467
-								'label' => esc_html( 'page_parent' ),
468
-								'value' => $args['page_parent'],
469
-							),
470
-							'compiler'         => array(
471
-								'label' => esc_html( 'compiler' ),
472
-								'value' => $args['compiler'] ? 'true' : 'false',
473
-							),
474
-							'output'           => array(
475
-								'label' => esc_html( 'output' ),
476
-								'value' => $args['output'] ? 'true' : 'false',
477
-							),
478
-							'output_tag'       => array(
479
-								'label' => esc_html( 'output_tag' ),
480
-								'value' => $args['output_tag'] ? 'true' : 'false',
481
-							),
482
-							'templates_path'   => array(
483
-								'label' => esc_html( 'templates_path' ),
484
-								'value' => $args['templates_path'],
485
-							),
486
-							'extensions'       => array(
487
-								'label' => esc_html( 'extensions' ),
488
-								'value' => $extensions,
489
-							),
490
-						),
491
-					);
492
-				}
493
-			}
494
-
495
-			return $debug_info;
496
-		}
497
-
498
-		/**
499
-		 * Register callback for autoload.
500
-		 *
501
-		 * @param string $class_name name of class.
502
-		 */
503
-		public function register_classes( string $class_name ) {
504
-			$class_name_test = self::strtolower( $class_name );
505
-
506
-			if ( strpos( $class_name_test, 'redux' ) === false ) {
507
-				return;
508
-			}
509
-
510
-			if ( ! class_exists( 'Redux_Functions_Ex' ) ) {
511
-				require_once Redux_Path::get_path( '/inc/classes/class-redux-functions-ex.php' );
512
-			}
513
-
514
-			if ( ! class_exists( $class_name ) ) {
515
-				// Backward compatibility for extensions sucks!
516
-				if ( 'Redux_Instances' === $class_name ) {
517
-					require_once Redux_Path::get_path( '/inc/classes/class-redux-instances.php' );
518
-					require_once Redux_Path::get_path( '/inc/lib/redux-instances.php' );
519
-
520
-					return;
521
-				}
522
-
523
-				// Load Redux APIs.
524
-				if ( 'Redux' === $class_name ) {
525
-					require_once Redux_Path::get_path( '/inc/classes/class-redux-api.php' );
526
-
527
-					return;
528
-				}
529
-
530
-				// Redux extra theme checks.
531
-				if ( 'Redux_ThemeCheck' === $class_name ) {
532
-					require_once Redux_Path::get_path( '/inc/themecheck/class-redux-themecheck.php' );
533
-
534
-					return;
535
-				}
536
-
537
-				if ( 'Redux_Welcome' === $class_name ) {
538
-					require_once Redux_Path::get_path( '/inc/welcome/class-redux-welcome.php' );
539
-
540
-					return;
541
-				}
542
-
543
-				$mappings = array(
544
-					'ReduxFrameworkInstances'  => 'Redux_Instances',
545
-					'reduxCorePanel'           => 'Redux_Panel',
546
-					'reduxCoreEnqueue'         => 'Redux_Enqueue',
547
-					'Redux_Abstract_Extension' => 'Redux_Extension_Abstract',
548
-				);
549
-				$alias    = false;
550
-				if ( isset( $mappings[ $class_name ] ) ) {
551
-					$alias      = $class_name;
552
-					$class_name = $mappings[ $class_name ];
553
-				}
554
-
555
-				// Everything else.
556
-				$file = 'class.' . $class_name_test . '.php';
557
-
558
-				$class_path = Redux_Path::get_path( '/inc/classes/' . $file );
559
-
560
-				if ( ! file_exists( $class_path ) ) {
561
-					$class_file_name = str_replace( '_', '-', $class_name );
562
-					$file            = 'class-' . $class_name_test . '.php';
563
-					$class_path      = Redux_Path::get_path( '/inc/classes/' . $file );
564
-				}
565
-
566
-				if ( file_exists( $class_path ) && ! class_exists( $class_name ) ) {
567
-					require_once $class_path;
568
-				}
569
-				if ( class_exists( $class_name ) && ! empty( $alias ) && ! class_exists( $alias ) ) {
570
-					class_alias( $class_name, $alias );
571
-				}
572
-			}
573
-
574
-			// phpcs:ignore WordPress.NamingConventions.ValidHookName
575
-			do_action( 'redux/core/includes', $this );
576
-		}
577
-
578
-		/**
579
-		 * Hooks to run on instance creation.
580
-		 */
581
-		private function hooks() {
582
-			// phpcs:ignore WordPress.NamingConventions.ValidHookName
583
-			do_action( 'redux/core/hooks', $this );
584
-		}
585
-
586
-		/**
587
-		 * Action to run on WordPress heartbeat.
588
-		 *
589
-		 * @return bool
590
-		 */
591
-		public static function is_heartbeat(): bool {
592
-			// Disregard WP AJAX 'heartbeat' call.  Why waste resources?
593
-			if ( isset( $_POST ) && isset( $_POST['_nonce'] ) && wp_verify_nonce( sanitize_key( wp_unslash( $_POST['_nonce'] ) ), 'heartbeat-nonce' ) ) {
594
-
595
-				if ( isset( $_POST['action'] ) && 'heartbeat' === sanitize_text_field( wp_unslash( $_POST['action'] ) ) ) {
596
-
597
-					// Hook, for purists.
598
-					if ( has_action( 'redux/ajax/heartbeat' ) ) {
599
-						// phpcs:ignore WordPress.NamingConventions.ValidHookName
600
-						do_action( 'redux/ajax/heartbeat' );
601
-					}
602
-
603
-					return true;
604
-				}
605
-
606
-				return false;
607
-			}
608
-
609
-			// Buh bye!
610
-			return false;
611
-		}
612
-
613
-		/**
614
-		 * Helper method to check for mb_strtolower or to use the standard strtolower.
615
-		 *
616
-		 * @param string|null $str String to make lowercase.
617
-		 *
618
-		 * @return string|null
619
-		 */
620
-		public static function strtolower( ?string $str ): string {
621
-			if ( function_exists( 'mb_strtolower' ) && function_exists( 'mb_detect_encoding' ) ) {
622
-				return mb_strtolower( $str, mb_detect_encoding( $str ) );
623
-			} else {
624
-				return strtolower( $str );
625
-			}
626
-		}
627
-	}
628
-
629
-	/*
14
+    /**
15
+     * Class Redux_Core
16
+     */
17
+    class Redux_Core {
18
+
19
+        /**
20
+         * Class instance.
21
+         *
22
+         * @var null|Redux_Core
23
+         */
24
+        public static ?Redux_Core $instance = null;
25
+
26
+        /**
27
+         * Project version
28
+         *
29
+         * @var string
30
+         */
31
+        public static string $version;
32
+
33
+        /**
34
+         * Project directory.
35
+         *
36
+         * @var string.
37
+         */
38
+        public static string $dir;
39
+
40
+        /**
41
+         * Project URL.
42
+         *
43
+         * @var string.
44
+         */
45
+        public static string $url;
46
+
47
+        /**
48
+         * Base directory path.
49
+         *
50
+         * @var string
51
+         */
52
+        public static string $redux_path;
53
+
54
+        /**
55
+         * Absolute direction path to WordPress upload directory.
56
+         *
57
+         * @var string
58
+         */
59
+        public static string $upload_dir = '';
60
+
61
+        /**
62
+         * Full URL to WordPress upload directory.
63
+         *
64
+         * @var null|string
65
+         */
66
+        public static ?string $upload_url = '';
67
+
68
+        /**
69
+         * Set when Redux is run as a plugin.
70
+         *
71
+         * @var bool
72
+         */
73
+        public static bool $is_plugin = true;
74
+
75
+        /**
76
+         * Indicated in_theme or in_plugin.
77
+         *
78
+         * @var string
79
+         */
80
+        public static string $installed = '';
81
+
82
+        /**
83
+         * Set when Redux is run as a plugin.
84
+         *
85
+         * @var bool
86
+         */
87
+        public static bool $as_plugin = false;
88
+
89
+        /**
90
+         * Set when Redux is embedded within a theme.
91
+         *
92
+         * @var bool
93
+         */
94
+        public static bool $in_theme = false;
95
+
96
+        /**
97
+         * Pointer to an updated Google fonts array.
98
+         *
99
+         * @var array|null
100
+         */
101
+        public static ?array $updated_google_fonts = array();
102
+
103
+        /**
104
+         * List of files calling Redux.
105
+         *
106
+         * @var array|null
107
+         */
108
+        public static ?array $callers = array();
109
+
110
+        /**
111
+         * Pointer to _SERVER global.
112
+         *
113
+         * @var array|null
114
+         */
115
+        public static ?array $server = array();
116
+
117
+        /**
118
+         * Field folding information for localization.
119
+         *
120
+         * @var null|array
121
+         */
122
+        public static ?array $required = array();
123
+
124
+        /**
125
+         * Field child-folding information for localization.
126
+         *
127
+         * @var null|array
128
+         */
129
+        public static ?array $required_child = array();
130
+
131
+        /**
132
+         * Array of fields to be folded.
133
+         *
134
+         * @var array|null
135
+         */
136
+        public static ?array $folds = array();
137
+
138
+        /**
139
+         * Array of fields that didn't pass the fold dependency test and are hidden.
140
+         *
141
+         * @var null|array
142
+         */
143
+        public static ?array $fields_hidden = array();
144
+
145
+        /**
146
+         * Values to generate google font CSS.
147
+         *
148
+         * @var null|array
149
+         */
150
+        public static ?array $typography = array();
151
+
152
+        /**
153
+         * Validation ran flag.
154
+         *
155
+         * @var bool
156
+         */
157
+        public static bool $validation_ran = false;
158
+
159
+        /**
160
+         * No output flag.
161
+         *
162
+         * @var bool
163
+         */
164
+        public static bool $no_output = false;
165
+
166
+        /**
167
+         * Array of fonts used by the panel for localization.
168
+         *
169
+         * @var null|array
170
+         */
171
+        public static ?array $fonts = array();
172
+
173
+        /**
174
+         * Array of Google fonts used by the panel for localization.
175
+         *
176
+         * @var null|array
177
+         */
178
+        public static ?array $google_array = array();
179
+
180
+        /**
181
+         * Array of various font groups used within the typography field.
182
+         *
183
+         * @var null|array
184
+         */
185
+        public static ?array $font_groups = array();
186
+
187
+        /**
188
+         * File system object used for I/O file operations.  Done the WordPress way.
189
+         *
190
+         * @var null|object
191
+         */
192
+        public static ?object $filesystem;
193
+
194
+        /**
195
+         * Pointer to the third party fixes class.
196
+         *
197
+         * @var Redux_ThirdParty_Fixes
198
+         */
199
+        public static Redux_ThirdParty_Fixes $third_party_fixes;
200
+
201
+        /**
202
+         * Redux Welcome screen object.
203
+         *
204
+         * @var Redux_Welcome
205
+         */
206
+        public static Redux_Welcome $welcome;
207
+
208
+        /**
209
+         * Creates instance of class.
210
+         *
211
+         * @return Redux_Core
212
+         * @throws Exception Comment.
213
+         */
214
+        public static function instance(): ?Redux_Core {
215
+            if ( ! self::$instance ) {
216
+                self::$instance = new self();
217
+
218
+                self::$instance->includes();
219
+                self::$instance->init();
220
+                self::$instance->hooks();
221
+
222
+                add_action( 'plugins_loaded', array( 'Redux_Core', 'plugins_loaded' ) );
223
+            }
224
+
225
+            return self::$instance;
226
+        }
227
+
228
+        /**
229
+         * Things to run after pluggable.php had loaded.
230
+         */
231
+        public static function plugins_loaded() {}
232
+
233
+        /**
234
+         * Class init.
235
+         */
236
+        private function init() {
237
+            self::$server = array(
238
+                'SERVER_SOFTWARE'      => '',
239
+                'REMOTE_ADDR'          => Redux_Helpers::is_local_host() ? '127.0.0.1' : '',
240
+                'HTTP_USER_AGENT'      => '',
241
+                'HTTP_HOST'            => '',
242
+                'REQUEST_URI'          => '',
243
+                'HTTP_X_FORWARDED_FOR' => '',
244
+            );
245
+
246
+            // phpcs:disable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
247
+            if ( ! empty( $_SERVER['SERVER_SOFTWARE'] ) ) {
248
+                self::$server['SERVER_SOFTWARE'] = sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) );
249
+            }
250
+            if ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) {
251
+                self::$server['REMOTE_ADDR'] = sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) );
252
+            }
253
+            if ( ! empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
254
+                self::$server['HTTP_USER_AGENT'] = sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) );
255
+            }
256
+            if ( ! empty( $_SERVER['HTTP_HOST'] ) ) {
257
+                self::$server['HTTP_HOST'] = sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) );
258
+            }
259
+            if ( ! empty( $_SERVER['REQUEST_URI'] ) ) {
260
+                self::$server['REQUEST_URI'] = sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) );
261
+            }
262
+            if ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
263
+                self::$server['HTTP_X_FORWARDED_FOR'] = sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_FORWARDED_FOR'] ) );
264
+            }
265
+            // phpcs:enable
266
+
267
+            self::$dir = trailingslashit( wp_normalize_path( dirname( realpath( __FILE__ ) ) ) );
268
+
269
+            Redux_Functions_Ex::generator();
270
+
271
+            if ( defined( 'REDUX_PLUGIN_FILE' ) ) {
272
+                $plugin_info = Redux_Functions_Ex::is_inside_plugin( REDUX_PLUGIN_FILE );
273
+            }
274
+
275
+            $plugin_info = Redux_Functions_Ex::is_inside_plugin( __FILE__ );
276
+
277
+            if ( false !== $plugin_info ) {
278
+                self::$installed = class_exists( 'Redux_Framework_Plugin' ) ? 'plugin' : 'in_plugin';
279
+                self::$is_plugin = class_exists( 'Redux_Framework_Plugin' );
280
+                self::$as_plugin = true;
281
+                self::$url       = trailingslashit( dirname( $plugin_info['url'] ) );
282
+            } else {
283
+                $theme_info = Redux_Functions_Ex::is_inside_theme( __FILE__ );
284
+                if ( false !== $theme_info ) {
285
+                    self::$url       = trailingslashit( dirname( $theme_info['url'] ) );
286
+                    self::$in_theme  = true;
287
+                    self::$installed = 'in_theme';
288
+                }
289
+            }
290
+
291
+            // phpcs:ignore WordPress.NamingConventions.ValidHookName
292
+            self::$url = apply_filters( 'redux/url', self::$url );
293
+
294
+            // phpcs:ignore WordPress.NamingConventions.ValidHookName
295
+            self::$dir = apply_filters( 'redux/dir', self::$dir );
296
+
297
+            // phpcs:ignore WordPress.NamingConventions.ValidHookName
298
+            self::$is_plugin = apply_filters( 'redux/is_plugin', self::$is_plugin );
299
+
300
+            if ( ! function_exists( 'current_time' ) ) {
301
+                require_once ABSPATH . '/wp-includes/functions.php';
302
+            }
303
+
304
+            $upload_dir       = wp_upload_dir();
305
+            self::$upload_dir = $upload_dir['basedir'] . '/redux/';
306
+            self::$upload_url = str_replace( array( 'https://', 'http://' ), '//', $upload_dir['baseurl'] . '/redux/' );
307
+
308
+            // phpcs:ignore WordPress.NamingConventions.ValidHookName
309
+            self::$upload_dir = apply_filters( 'redux/upload_dir', self::$upload_dir );
310
+
311
+            // phpcs:ignore WordPress.NamingConventions.ValidHookName
312
+            self::$upload_url = apply_filters( 'redux/upload_url', self::$upload_url );
313
+        }
314
+
315
+        /**
316
+         * Code to execute on a framework __construct.
317
+         *
318
+         * @param ReduxFramework $redux Pointer to ReduxFramework object.
319
+         */
320
+        public static function core_construct( ReduxFramework $redux ) {
321
+            self::$third_party_fixes = new Redux_ThirdParty_Fixes( $redux );
322
+
323
+            Redux_ThemeCheck::get_instance();
324
+        }
325
+
326
+        /**
327
+         * Autoregister run.
328
+         *
329
+         * @throws Exception Comment.
330
+         */
331
+        private function includes() {
332
+            if ( is_admin() ) {
333
+                if ( class_exists( 'Redux_Pro' ) && isset( Redux_Pro::$dir ) ) {
334
+                    echo '<div class="error"><p>' . sprintf( esc_html__( 'Redux has detected the Redux Pro plugin is enabled. All featured of Redux Pro are now part of the entire Redux plugin and is no longer required. Please disable the Redux Pro plugin to avoid potential conflicts.', 'redux-framework' ), '<code></code>' ) . '</p></div>';
335
+                }
336
+            }
337
+
338
+            require_once __DIR__ . '/inc/classes/class-redux-path.php';
339
+            require_once __DIR__ . '/inc/classes/class-redux-functions-ex.php';
340
+            require_once __DIR__ . '/inc/classes/class-redux-helpers.php';
341
+            require_once __DIR__ . '/inc/classes/class-redux-instances.php';
342
+
343
+            Redux_Functions_Ex::register_class_path( 'Redux', __DIR__ . '/inc/classes' );
344
+            Redux_Functions_Ex::register_class_path( 'Redux', __DIR__ . '/inc/welcome' );
345
+
346
+            spl_autoload_register( array( $this, 'register_classes' ) );
347
+
348
+            self::$welcome = new Redux_Welcome();
349
+
350
+            add_filter( 'debug_information', array( $this, 'add_debug_info' ) );
351
+        }
352
+
353
+        /**
354
+         * Add debug info for the WP Site Health screen.
355
+         *
356
+         * @param array $debug_info Debug data.
357
+         *
358
+         * @return array
359
+         * @throws ReflectionException Exception.
360
+         */
361
+        public function add_debug_info( array $debug_info ): array {
362
+
363
+            // Get browser data.
364
+            if ( ! class_exists( 'ReduxBrowser' ) ) {
365
+                require_once self::$dir . 'inc/lib/browser.php';
366
+            }
367
+
368
+            $browser = new ReduxBrowser();
369
+
370
+            $browser_data = array(
371
+                'Agent'    => $browser->getUserAgent(),
372
+                'Browser'  => $browser->getBrowser(),
373
+                'Version'  => $browser->getVersion(),
374
+                'Platform' => $browser->getPlatform(),
375
+            );
376
+
377
+            // Set Redux dir permission results to Site Health screen.
378
+            $debug_info['wp-filesystem']['fields'][] = array(
379
+                'label' => esc_html__( 'The Redux upload directory', 'redux-framework' ),
380
+                'value' => wp_is_writable( self::$upload_dir ) ? 'Writable' : 'Not writable',
381
+            );
382
+
383
+            // Set Redux plugin results to Site Health screen.
384
+            $debug_info['redux-framework'] = array(
385
+                'label'       => esc_html__( 'Redux Framework', 'redux-framework' ),
386
+                'description' => esc_html__( 'Debug information specific to Redux Framework.', 'redux-framework' ),
387
+                'fields'      => array(
388
+                    'version'        => array(
389
+                        'label' => esc_html__( 'Version', 'redux-framework' ),
390
+                        'value' => self::$version,
391
+                    ),
392
+                    'installation'   => array(
393
+                        'label' => esc_html__( 'Installation', 'redux-framework' ),
394
+                        'value' => self::$installed,
395
+                    ),
396
+                    'data directory' => array(
397
+                        'label' => esc_html__( 'Data directory', 'redux-framework' ),
398
+                        'value' => self::$dir,
399
+                    ),
400
+                    'browser'        => array(
401
+                        'label' => esc_html__( 'Browser', 'redux-framework' ),
402
+                        'value' => $browser_data,
403
+                    ),
404
+                ),
405
+            );
406
+
407
+            $redux = Redux::all_instances();
408
+
409
+            $extensions = array();
410
+
411
+            if ( ! empty( $redux ) && is_array( $redux ) ) {
412
+                foreach ( $redux as $inst => $data ) {
413
+                    Redux::init( $inst );
414
+
415
+                    $inst_name = ucwords( str_replace( array( '_', '-' ), ' ', $inst ) );
416
+                    $args      = $data->args;
417
+
418
+                    $ext = Redux::get_extensions( $inst );
419
+                    if ( ! empty( $ext ) && is_array( $ext ) ) {
420
+                        ksort( $ext );
421
+
422
+                        foreach ( $ext as $name => $arr ) {
423
+                            $ver = $arr['version'];
424
+
425
+                            $ex = esc_html( ucwords( str_replace( array( '_', '-' ), ' ', $name ) ) );
426
+
427
+                            $extensions[ $ex ] = esc_html( $ver );
428
+                        }
429
+                    }
430
+
431
+                    // Output Redux instances.
432
+                    $debug_info[ 'redux-instance-' . $inst ] = array(
433
+                        // translators: %s = Instance name.
434
+                        'label'       => sprintf( esc_html__( 'Redux Instance: %s', 'redux-framework' ), $inst_name ),
435
+                        // translators: %s = Instance name w/ HTML.
436
+                        'description' => sprintf( esc_html__( 'Debug information for the %s Redux instance.', 'redux-framework' ), '<code>' . $inst . '</code>' ),
437
+                        'fields'      => array(
438
+                            'opt_name'         => array(
439
+                                'label' => esc_html( 'opt_name' ),
440
+                                'value' => $args['opt_name'],
441
+                            ),
442
+                            'global_variable'  => array(
443
+                                'label' => esc_html( 'global_variable' ),
444
+                                'value' => $args['global_variable'],
445
+                            ),
446
+                            'dev_mode'         => array(
447
+                                'label' => esc_html( 'dev_mode' ),
448
+                                'value' => $args['dev_mode'] ? 'true' : 'false',
449
+                            ),
450
+                            'ajax_save'        => array(
451
+                                'label' => esc_html( 'ajax_save' ),
452
+                                'value' => $args['ajax_save'] ? 'true' : 'false',
453
+                            ),
454
+                            'page_slug'        => array(
455
+                                'label' => esc_html( 'page_slug' ),
456
+                                'value' => $args['page_slug'],
457
+                            ),
458
+                            'page_permissions' => array(
459
+                                'label' => esc_html( 'page_permissions' ),
460
+                                'value' => $args['page_permissions'],
461
+                            ),
462
+                            'menu_type'        => array(
463
+                                'label' => esc_html( 'menu_type' ),
464
+                                'value' => $args['menu_type'],
465
+                            ),
466
+                            'page_parent'      => array(
467
+                                'label' => esc_html( 'page_parent' ),
468
+                                'value' => $args['page_parent'],
469
+                            ),
470
+                            'compiler'         => array(
471
+                                'label' => esc_html( 'compiler' ),
472
+                                'value' => $args['compiler'] ? 'true' : 'false',
473
+                            ),
474
+                            'output'           => array(
475
+                                'label' => esc_html( 'output' ),
476
+                                'value' => $args['output'] ? 'true' : 'false',
477
+                            ),
478
+                            'output_tag'       => array(
479
+                                'label' => esc_html( 'output_tag' ),
480
+                                'value' => $args['output_tag'] ? 'true' : 'false',
481
+                            ),
482
+                            'templates_path'   => array(
483
+                                'label' => esc_html( 'templates_path' ),
484
+                                'value' => $args['templates_path'],
485
+                            ),
486
+                            'extensions'       => array(
487
+                                'label' => esc_html( 'extensions' ),
488
+                                'value' => $extensions,
489
+                            ),
490
+                        ),
491
+                    );
492
+                }
493
+            }
494
+
495
+            return $debug_info;
496
+        }
497
+
498
+        /**
499
+         * Register callback for autoload.
500
+         *
501
+         * @param string $class_name name of class.
502
+         */
503
+        public function register_classes( string $class_name ) {
504
+            $class_name_test = self::strtolower( $class_name );
505
+
506
+            if ( strpos( $class_name_test, 'redux' ) === false ) {
507
+                return;
508
+            }
509
+
510
+            if ( ! class_exists( 'Redux_Functions_Ex' ) ) {
511
+                require_once Redux_Path::get_path( '/inc/classes/class-redux-functions-ex.php' );
512
+            }
513
+
514
+            if ( ! class_exists( $class_name ) ) {
515
+                // Backward compatibility for extensions sucks!
516
+                if ( 'Redux_Instances' === $class_name ) {
517
+                    require_once Redux_Path::get_path( '/inc/classes/class-redux-instances.php' );
518
+                    require_once Redux_Path::get_path( '/inc/lib/redux-instances.php' );
519
+
520
+                    return;
521
+                }
522
+
523
+                // Load Redux APIs.
524
+                if ( 'Redux' === $class_name ) {
525
+                    require_once Redux_Path::get_path( '/inc/classes/class-redux-api.php' );
526
+
527
+                    return;
528
+                }
529
+
530
+                // Redux extra theme checks.
531
+                if ( 'Redux_ThemeCheck' === $class_name ) {
532
+                    require_once Redux_Path::get_path( '/inc/themecheck/class-redux-themecheck.php' );
533
+
534
+                    return;
535
+                }
536
+
537
+                if ( 'Redux_Welcome' === $class_name ) {
538
+                    require_once Redux_Path::get_path( '/inc/welcome/class-redux-welcome.php' );
539
+
540
+                    return;
541
+                }
542
+
543
+                $mappings = array(
544
+                    'ReduxFrameworkInstances'  => 'Redux_Instances',
545
+                    'reduxCorePanel'           => 'Redux_Panel',
546
+                    'reduxCoreEnqueue'         => 'Redux_Enqueue',
547
+                    'Redux_Abstract_Extension' => 'Redux_Extension_Abstract',
548
+                );
549
+                $alias    = false;
550
+                if ( isset( $mappings[ $class_name ] ) ) {
551
+                    $alias      = $class_name;
552
+                    $class_name = $mappings[ $class_name ];
553
+                }
554
+
555
+                // Everything else.
556
+                $file = 'class.' . $class_name_test . '.php';
557
+
558
+                $class_path = Redux_Path::get_path( '/inc/classes/' . $file );
559
+
560
+                if ( ! file_exists( $class_path ) ) {
561
+                    $class_file_name = str_replace( '_', '-', $class_name );
562
+                    $file            = 'class-' . $class_name_test . '.php';
563
+                    $class_path      = Redux_Path::get_path( '/inc/classes/' . $file );
564
+                }
565
+
566
+                if ( file_exists( $class_path ) && ! class_exists( $class_name ) ) {
567
+                    require_once $class_path;
568
+                }
569
+                if ( class_exists( $class_name ) && ! empty( $alias ) && ! class_exists( $alias ) ) {
570
+                    class_alias( $class_name, $alias );
571
+                }
572
+            }
573
+
574
+            // phpcs:ignore WordPress.NamingConventions.ValidHookName
575
+            do_action( 'redux/core/includes', $this );
576
+        }
577
+
578
+        /**
579
+         * Hooks to run on instance creation.
580
+         */
581
+        private function hooks() {
582
+            // phpcs:ignore WordPress.NamingConventions.ValidHookName
583
+            do_action( 'redux/core/hooks', $this );
584
+        }
585
+
586
+        /**
587
+         * Action to run on WordPress heartbeat.
588
+         *
589
+         * @return bool
590
+         */
591
+        public static function is_heartbeat(): bool {
592
+            // Disregard WP AJAX 'heartbeat' call.  Why waste resources?
593
+            if ( isset( $_POST ) && isset( $_POST['_nonce'] ) && wp_verify_nonce( sanitize_key( wp_unslash( $_POST['_nonce'] ) ), 'heartbeat-nonce' ) ) {
594
+
595
+                if ( isset( $_POST['action'] ) && 'heartbeat' === sanitize_text_field( wp_unslash( $_POST['action'] ) ) ) {
596
+
597
+                    // Hook, for purists.
598
+                    if ( has_action( 'redux/ajax/heartbeat' ) ) {
599
+                        // phpcs:ignore WordPress.NamingConventions.ValidHookName
600
+                        do_action( 'redux/ajax/heartbeat' );
601
+                    }
602
+
603
+                    return true;
604
+                }
605
+
606
+                return false;
607
+            }
608
+
609
+            // Buh bye!
610
+            return false;
611
+        }
612
+
613
+        /**
614
+         * Helper method to check for mb_strtolower or to use the standard strtolower.
615
+         *
616
+         * @param string|null $str String to make lowercase.
617
+         *
618
+         * @return string|null
619
+         */
620
+        public static function strtolower( ?string $str ): string {
621
+            if ( function_exists( 'mb_strtolower' ) && function_exists( 'mb_detect_encoding' ) ) {
622
+                return mb_strtolower( $str, mb_detect_encoding( $str ) );
623
+            } else {
624
+                return strtolower( $str );
625
+            }
626
+        }
627
+    }
628
+
629
+    /*
630 630
 	 * Backwards comparability alias
631 631
 	 */
632
-	class_alias( 'Redux_Core', 'redux-core' );
632
+    class_alias( 'Redux_Core', 'redux-core' );
633 633
 }
Please login to merge, or discard this patch.
redux-core/inc/classes/class-redux-rate-limiter.php 2 patches
Indentation   +60 added lines, -60 removed lines patch added patch discarded remove patch
@@ -12,75 +12,75 @@
 block discarded – undo
12 12
 
13 13
 if ( ! class_exists( 'Redux_Rate_Limiter', false ) ) {
14 14
 
15
-	/**
16
-	 * Redux_Rate_Limiter.
17
-	 *
18
-	 * @since 4.5.10
19
-	 */
20
-	class Redux_Rate_Limiter {
15
+    /**
16
+     * Redux_Rate_Limiter.
17
+     *
18
+     * @since 4.5.10
19
+     */
20
+    class Redux_Rate_Limiter {
21 21
 
22
-		/**
23
-		 * Limits for functions that require them.
24
-		 *
25
-		 * @var array[]
26
-		 */
27
-		private static array $limits = array(
28
-			'download_options' => array(
29
-				'max'    => 5,
30
-				'window' => 300,
31
-			),  // 5 per 5 minutes.
32
-			'color_schemes'    => array(
33
-				'max'    => 5,
34
-				'window' => 300,
35
-			), // 5 per 5 minutes.
36
-		);
22
+        /**
23
+         * Limits for functions that require them.
24
+         *
25
+         * @var array[]
26
+         */
27
+        private static array $limits = array(
28
+            'download_options' => array(
29
+                'max'    => 5,
30
+                'window' => 300,
31
+            ),  // 5 per 5 minutes.
32
+            'color_schemes'    => array(
33
+                'max'    => 5,
34
+                'window' => 300,
35
+            ), // 5 per 5 minutes.
36
+        );
37 37
 
38
-		/**
39
-		 * Check for the rate limit.
40
-		 *
41
-		 * @param string $action Function to check.
42
-		 *
43
-		 * @return bool
44
-		 */
45
-		public static function check( string $action ): bool {
46
-			if ( ! isset( self::$limits[ $action ] ) ) {
47
-				return true;
48
-			}
38
+        /**
39
+         * Check for the rate limit.
40
+         *
41
+         * @param string $action Function to check.
42
+         *
43
+         * @return bool
44
+         */
45
+        public static function check( string $action ): bool {
46
+            if ( ! isset( self::$limits[ $action ] ) ) {
47
+                return true;
48
+            }
49 49
 
50
-			$limit = self::$limits[ $action ];
50
+            $limit = self::$limits[ $action ];
51 51
 
52
-			$ip  = self::get_client_ip();
53
-			$key = 'redux_rate_' . md5( $action . $ip );
52
+            $ip  = self::get_client_ip();
53
+            $key = 'redux_rate_' . md5( $action . $ip );
54 54
 
55
-			$current = get_transient( $key );
55
+            $current = get_transient( $key );
56 56
 
57
-			if ( false === $current ) {
58
-				set_transient( $key, 1, $limit['window'] );
59
-				return true;
60
-			}
57
+            if ( false === $current ) {
58
+                set_transient( $key, 1, $limit['window'] );
59
+                return true;
60
+            }
61 61
 
62
-			if ( $current >= $limit['max'] ) {
63
-				return false; // Rate limited.
64
-			}
62
+            if ( $current >= $limit['max'] ) {
63
+                return false; // Rate limited.
64
+            }
65 65
 
66
-			set_transient( $key, $current + 1, $limit['window'] );
67
-			return true;
68
-		}
66
+            set_transient( $key, $current + 1, $limit['window'] );
67
+            return true;
68
+        }
69 69
 
70
-		/**
71
-		 * Get the client's IP address.
72
-		 *
73
-		 * @return mixed|string
74
-		 */
75
-		private static function get_client_ip() {
76
-			$ip = Redux_Core::$server['REMOTE_ADDR'];
70
+        /**
71
+         * Get the client's IP address.
72
+         *
73
+         * @return mixed|string
74
+         */
75
+        private static function get_client_ip() {
76
+            $ip = Redux_Core::$server['REMOTE_ADDR'];
77 77
 
78
-			if ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
79
-				$ips = explode( ',', Redux_Core::$server['HTTP_X_FORWARDED_FOR'] );
80
-				$ip  = trim( $ips[0] );
81
-			}
78
+            if ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
79
+                $ips = explode( ',', Redux_Core::$server['HTTP_X_FORWARDED_FOR'] );
80
+                $ip  = trim( $ips[0] );
81
+            }
82 82
 
83
-			return filter_var( $ip, FILTER_VALIDATE_IP ) ?? '0.0.0.0';
84
-		}
85
-	}
83
+            return filter_var( $ip, FILTER_VALIDATE_IP ) ?? '0.0.0.0';
84
+        }
85
+    }
86 86
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -28,7 +28,7 @@  discard block
 block discarded – undo
28 28
 			'download_options' => array(
29 29
 				'max'    => 5,
30 30
 				'window' => 300,
31
-			),  // 5 per 5 minutes.
31
+			), // 5 per 5 minutes.
32 32
 			'color_schemes'    => array(
33 33
 				'max'    => 5,
34 34
 				'window' => 300,
@@ -43,11 +43,11 @@  discard block
 block discarded – undo
43 43
 		 * @return bool
44 44
 		 */
45 45
 		public static function check( string $action ): bool {
46
-			if ( ! isset( self::$limits[ $action ] ) ) {
46
+			if ( ! isset( self::$limits[$action] ) ) {
47 47
 				return true;
48 48
 			}
49 49
 
50
-			$limit = self::$limits[ $action ];
50
+			$limit = self::$limits[$action];
51 51
 
52 52
 			$ip  = self::get_client_ip();
53 53
 			$key = 'redux_rate_' . md5( $action . $ip );
Please login to merge, or discard this patch.
inc/extensions/color_scheme/class-redux-extension-color-scheme.php 1 patch
Indentation   +784 added lines, -784 removed lines patch added patch discarded remove patch
@@ -16,795 +16,795 @@
 block discarded – undo
16 16
 // Don't duplicate me!
17 17
 if ( ! class_exists( 'Redux_Extension_Color_Scheme' ) ) {
18 18
 
19
-	/**
20
-	 * Class Redux_Extension_Color_Scheme
21
-	 */
22
-	class Redux_Extension_Color_Scheme extends Redux_Extension_Abstract {
23
-
24
-		/**
25
-		 * Extension version.
26
-		 *
27
-		 * @var string
28
-		 */
29
-		public static $version = '4.5.10';
30
-
31
-		/**
32
-		 * Extension friendly name.
33
-		 *
34
-		 * @var string
35
-		 */
36
-		public string $extension_name = 'Color Schemes';
37
-
38
-		/**
39
-		 * Field ID.
40
-		 *
41
-		 * @var string
42
-		 */
43
-		public $field_id = '';
44
-
45
-		/**
46
-		 * Transparent output bit.
47
-		 *
48
-		 * @var bool
49
-		 */
50
-		public bool $output_transparent = false;
51
-
52
-		/**
53
-		 * Extension field name.
54
-		 *
55
-		 * @var string
56
-		 */
57
-		public string $field_name = '';
58
-
59
-		/**
60
-		 * Class Constructor. Defines the args for the extensions class
61
-		 *
62
-		 * @since       1.0.0
63
-		 * @access      public
64
-		 *
65
-		 * @param       object $redux Parent settings.
66
-		 *
67
-		 * @return      void
68
-		 */
69
-		public function __construct( $redux ) {
70
-			parent::__construct( $redux, __FILE__ );
19
+    /**
20
+     * Class Redux_Extension_Color_Scheme
21
+     */
22
+    class Redux_Extension_Color_Scheme extends Redux_Extension_Abstract {
23
+
24
+        /**
25
+         * Extension version.
26
+         *
27
+         * @var string
28
+         */
29
+        public static $version = '4.5.10';
30
+
31
+        /**
32
+         * Extension friendly name.
33
+         *
34
+         * @var string
35
+         */
36
+        public string $extension_name = 'Color Schemes';
37
+
38
+        /**
39
+         * Field ID.
40
+         *
41
+         * @var string
42
+         */
43
+        public $field_id = '';
44
+
45
+        /**
46
+         * Transparent output bit.
47
+         *
48
+         * @var bool
49
+         */
50
+        public bool $output_transparent = false;
51
+
52
+        /**
53
+         * Extension field name.
54
+         *
55
+         * @var string
56
+         */
57
+        public string $field_name = '';
58
+
59
+        /**
60
+         * Class Constructor. Defines the args for the extensions class
61
+         *
62
+         * @since       1.0.0
63
+         * @access      public
64
+         *
65
+         * @param       object $redux Parent settings.
66
+         *
67
+         * @return      void
68
+         */
69
+        public function __construct( $redux ) {
70
+            parent::__construct( $redux, __FILE__ );
71 71
 
72
-			$this->add_field( 'color_scheme' );
73
-			$this->field_name = 'color_scheme';
72
+            $this->add_field( 'color_scheme' );
73
+            $this->field_name = 'color_scheme';
74 74
 
75
-			add_filter( "redux/options/{$this->parent->args['opt_name']}/defaults", array( $this, 'set_defaults' ) );
75
+            add_filter( "redux/options/{$this->parent->args['opt_name']}/defaults", array( $this, 'set_defaults' ) );
76 76
 
77
-			// Ajax hooks.
78
-			add_action( 'wp_ajax_redux_color_schemes', array( $this, 'parse_ajax' ) );
79
-
80
-			// Reset hooks.
81
-			add_action( 'redux/validate/' . $this->parent->args['opt_name'] . '/defaults', array( $this, 'reset_defaults' ), 0, 3 );
82
-			add_action( 'redux/validate/' . $this->parent->args['opt_name'] . '/defaults_section', array( $this, 'reset_defaults_section' ), 0, 3 );
83
-
84
-			// Save filter.
85
-			add_action( 'redux/validate/' . $this->parent->args['opt_name'] . '/before_validation', array( $this, 'save_hook' ), 0, 3 );
86
-
87
-			// Register hook - to get field id and prep helper.
88
-			add_action( 'redux/options/' . $this->parent->args['opt_name'] . '/field/' . $this->field_name . '/register', array( $this, 'register_field' ) );
89
-
90
-			include_once $this->extension_dir . 'color_scheme/inc/class-redux-color-scheme-functions.php';
91
-			Redux_Color_Scheme_Functions::init( $redux );
92
-
93
-			$field = Redux_Color_Scheme_Functions::get_field( $redux );
94
-
95
-			if ( ! is_array( $field ) ) {
96
-				return;
97
-			}
98
-
99
-			$this->field_id = $field['id'];
100
-
101
-			// Prep storage.
102
-			$upload_dir = Redux_Color_Scheme_Functions::$upload_dir;
103
-
104
-			// Create uploads/redux_scheme_colors/ folder.
105
-			if ( ! is_dir( $upload_dir ) ) {
106
-				Redux_Core::$filesystem->execute( 'mkdir', $upload_dir );
107
-			}
108
-		}
77
+            // Ajax hooks.
78
+            add_action( 'wp_ajax_redux_color_schemes', array( $this, 'parse_ajax' ) );
79
+
80
+            // Reset hooks.
81
+            add_action( 'redux/validate/' . $this->parent->args['opt_name'] . '/defaults', array( $this, 'reset_defaults' ), 0, 3 );
82
+            add_action( 'redux/validate/' . $this->parent->args['opt_name'] . '/defaults_section', array( $this, 'reset_defaults_section' ), 0, 3 );
83
+
84
+            // Save filter.
85
+            add_action( 'redux/validate/' . $this->parent->args['opt_name'] . '/before_validation', array( $this, 'save_hook' ), 0, 3 );
86
+
87
+            // Register hook - to get field id and prep helper.
88
+            add_action( 'redux/options/' . $this->parent->args['opt_name'] . '/field/' . $this->field_name . '/register', array( $this, 'register_field' ) );
89
+
90
+            include_once $this->extension_dir . 'color_scheme/inc/class-redux-color-scheme-functions.php';
91
+            Redux_Color_Scheme_Functions::init( $redux );
92
+
93
+            $field = Redux_Color_Scheme_Functions::get_field( $redux );
94
+
95
+            if ( ! is_array( $field ) ) {
96
+                return;
97
+            }
98
+
99
+            $this->field_id = $field['id'];
100
+
101
+            // Prep storage.
102
+            $upload_dir = Redux_Color_Scheme_Functions::$upload_dir;
103
+
104
+            // Create uploads/redux_scheme_colors/ folder.
105
+            if ( ! is_dir( $upload_dir ) ) {
106
+                Redux_Core::$filesystem->execute( 'mkdir', $upload_dir );
107
+            }
108
+        }
109 109
 
110
-		/**
111
-		 * Set default values after reset.
112
-		 *
113
-		 * @param array $defaults Default values.
114
-		 *
115
-		 * @return array
116
-		 */
117
-		public function set_defaults( array $defaults = array() ): array {
118
-			if ( ! Redux_Helpers::is_field_in_use( $this->parent, 'color_scheme' ) ) {
119
-				return $defaults;
120
-			}
121
-
122
-			if ( empty( $this->field_id ) ) {
123
-				return $defaults;
124
-			}
125
-
126
-			$x            = get_option( $this->parent->args['opt_name'] );
127
-			$color_opts   = $x[ $this->field_id ] ?? array();
128
-			$wrong_format = false;
129
-
130
-			if ( ! isset( $color_opts['color_scheme_name'] ) ) {
131
-				$wrong_format = true;
132
-
133
-				$data = Redux_Color_Scheme_Functions::data_array_from_scheme( 'Default' );
134
-
135
-				if ( ! empty( $data ) && isset( $x[ $this->field_id ] ) ) {
136
-					$x[ $this->field_id ] = $data;
137
-
138
-					update_option( $this->parent->args['opt_name'], $x );
139
-				}
140
-			}
141
-
142
-			Redux_Color_Scheme_Functions::$parent = $this->parent;
143
-
144
-			$ot_val                   = Redux_Color_Scheme_Functions::get_output_transparent_val();
145
-			$this->output_transparent = $ot_val;
146
-
147
-			Redux_Color_Scheme_Functions::convert_to_db();
148
-
149
-			$scheme_key  = Redux_Color_Scheme_Functions::get_scheme_key();
150
-			$scheme_data = get_option( $scheme_key );
151
-
152
-			$scheme_data_exists = ! empty( $scheme_data );
153
-
154
-			$default_exists = in_array( 'default', array_map( 'strtolower', Redux_Color_Scheme_Functions::get_scheme_names() ), true );
155
-
156
-			if ( ! $scheme_data_exists || ! $default_exists || $wrong_format ) {
157
-				$data = $this->get_default_data();
158
-
159
-				// Add to (and/or create) JSON scheme file.
160
-				Redux_Color_Scheme_Functions::set_scheme_data( 'Default', $data );
161
-
162
-				// Set default scheme.
163
-				Redux_Color_Scheme_Functions::set_current_scheme_id( 'Default' );
164
-
165
-				$data = Redux_Color_Scheme_Functions::data_array_from_scheme( 'Default' );
166
-
167
-				$this->parent->options[ $this->field_id ] = $data;
168
-
169
-				$defaults[ $this->field_id ] = $data;
170
-			}
171
-
172
-			return $defaults;
173
-		}
174
-
175
-		/**
176
-		 * Field Register. Sets the whole smash up.
177
-		 *
178
-		 * @param       array $data Field data.
179
-		 *
180
-		 * @return      array
181
-		 * @since       1.0.0
182
-		 * @access      public
183
-		 */
184
-		public function register_field( array $data ): array {
185
-
186
-			// Include color_scheme helper.
187
-			include_once $this->extension_dir . 'color_scheme/inc/class-redux-color-scheme-functions.php';
188
-
189
-			if ( isset( $data['output_transparent'] ) ) {
190
-				$this->output_transparent = $data['output_transparent'];
191
-			}
110
+        /**
111
+         * Set default values after reset.
112
+         *
113
+         * @param array $defaults Default values.
114
+         *
115
+         * @return array
116
+         */
117
+        public function set_defaults( array $defaults = array() ): array {
118
+            if ( ! Redux_Helpers::is_field_in_use( $this->parent, 'color_scheme' ) ) {
119
+                return $defaults;
120
+            }
121
+
122
+            if ( empty( $this->field_id ) ) {
123
+                return $defaults;
124
+            }
125
+
126
+            $x            = get_option( $this->parent->args['opt_name'] );
127
+            $color_opts   = $x[ $this->field_id ] ?? array();
128
+            $wrong_format = false;
129
+
130
+            if ( ! isset( $color_opts['color_scheme_name'] ) ) {
131
+                $wrong_format = true;
132
+
133
+                $data = Redux_Color_Scheme_Functions::data_array_from_scheme( 'Default' );
134
+
135
+                if ( ! empty( $data ) && isset( $x[ $this->field_id ] ) ) {
136
+                    $x[ $this->field_id ] = $data;
137
+
138
+                    update_option( $this->parent->args['opt_name'], $x );
139
+                }
140
+            }
141
+
142
+            Redux_Color_Scheme_Functions::$parent = $this->parent;
143
+
144
+            $ot_val                   = Redux_Color_Scheme_Functions::get_output_transparent_val();
145
+            $this->output_transparent = $ot_val;
146
+
147
+            Redux_Color_Scheme_Functions::convert_to_db();
148
+
149
+            $scheme_key  = Redux_Color_Scheme_Functions::get_scheme_key();
150
+            $scheme_data = get_option( $scheme_key );
151
+
152
+            $scheme_data_exists = ! empty( $scheme_data );
153
+
154
+            $default_exists = in_array( 'default', array_map( 'strtolower', Redux_Color_Scheme_Functions::get_scheme_names() ), true );
155
+
156
+            if ( ! $scheme_data_exists || ! $default_exists || $wrong_format ) {
157
+                $data = $this->get_default_data();
158
+
159
+                // Add to (and/or create) JSON scheme file.
160
+                Redux_Color_Scheme_Functions::set_scheme_data( 'Default', $data );
161
+
162
+                // Set default scheme.
163
+                Redux_Color_Scheme_Functions::set_current_scheme_id( 'Default' );
164
+
165
+                $data = Redux_Color_Scheme_Functions::data_array_from_scheme( 'Default' );
166
+
167
+                $this->parent->options[ $this->field_id ] = $data;
168
+
169
+                $defaults[ $this->field_id ] = $data;
170
+            }
171
+
172
+            return $defaults;
173
+        }
174
+
175
+        /**
176
+         * Field Register. Sets the whole smash up.
177
+         *
178
+         * @param       array $data Field data.
179
+         *
180
+         * @return      array
181
+         * @since       1.0.0
182
+         * @access      public
183
+         */
184
+        public function register_field( array $data ): array {
185
+
186
+            // Include color_scheme helper.
187
+            include_once $this->extension_dir . 'color_scheme/inc/class-redux-color-scheme-functions.php';
188
+
189
+            if ( isset( $data['output_transparent'] ) ) {
190
+                $this->output_transparent = $data['output_transparent'];
191
+            }
192 192
 
193
-			$this->field_id                         = $data['id'];
194
-			Redux_Color_Scheme_Functions::$field_id = $data['id'];
195
-
196
-			// Set helper parent object.
197
-			Redux_Color_Scheme_Functions::$parent = $this->parent;
198
-
199
-			// Prep storage.
200
-			$upload_dir = Redux_Color_Scheme_Functions::$upload_dir;
201
-
202
-			// Set upload_dir cookie.
203
-			setcookie( 'redux_color_scheme_upload_dir', $upload_dir, 0, '/' );
204
-
205
-			return $data;
206
-		}
207
-
208
-		/**
209
-		 * Reset defaults.
210
-		 *
211
-		 * @param array $defaults Default values.
212
-		 *
213
-		 * @return array
214
-		 */
215
-		public function reset_defaults( array $defaults = array() ): array {
216
-			if ( Redux_Helpers::is_field_in_use( $this->parent, 'color_scheme' ) ) {
217
-				// Check if reset_all was fired.
218
-				$this->reset_all();
219
-				$defaults[ $this->field_id ] = Redux_Color_Scheme_Functions::data_array_from_scheme( 'Default' );
220
-			}
193
+            $this->field_id                         = $data['id'];
194
+            Redux_Color_Scheme_Functions::$field_id = $data['id'];
195
+
196
+            // Set helper parent object.
197
+            Redux_Color_Scheme_Functions::$parent = $this->parent;
198
+
199
+            // Prep storage.
200
+            $upload_dir = Redux_Color_Scheme_Functions::$upload_dir;
201
+
202
+            // Set upload_dir cookie.
203
+            setcookie( 'redux_color_scheme_upload_dir', $upload_dir, 0, '/' );
204
+
205
+            return $data;
206
+        }
207
+
208
+        /**
209
+         * Reset defaults.
210
+         *
211
+         * @param array $defaults Default values.
212
+         *
213
+         * @return array
214
+         */
215
+        public function reset_defaults( array $defaults = array() ): array {
216
+            if ( Redux_Helpers::is_field_in_use( $this->parent, 'color_scheme' ) ) {
217
+                // Check if reset_all was fired.
218
+                $this->reset_all();
219
+                $defaults[ $this->field_id ] = Redux_Color_Scheme_Functions::data_array_from_scheme( 'Default' );
220
+            }
221 221
 
222
-			return $defaults;
223
-		}
222
+            return $defaults;
223
+        }
224 224
 
225
-		/**
226
-		 * Reset section defaults.
227
-		 *
228
-		 * @param array $defaults Default values.
229
-		 *
230
-		 * @return array
231
-		 */
232
-		public function reset_defaults_section( array $defaults = array() ): array {
233
-			if ( Redux_Helpers::is_field_in_use( $this->parent, 'color_scheme' ) ) {
234
-				// Get the current tab/section number.
235
-				if ( isset( $_COOKIE['redux_current_tab'] ) ) {
236
-					$cur_tab = sanitize_text_field( wp_unslash( $_COOKIE['redux_current_tab'] ) );
237
-
238
-					// Get the tab/section number field is used on.
239
-					$tab_num = $this->parent->field_sections['color_scheme'][ $this->field_id ];
240
-
241
-					// Match...
242
-					if ( $cur_tab === $tab_num ) {
243
-
244
-						// Reset data.
245
-						$this->reset_all();
246
-					}
247
-					$defaults[ $this->field_id ] = Redux_Color_Scheme_Functions::data_array_from_scheme( 'Default' );
248
-				}
249
-			}
250
-
251
-			return $defaults;
252
-		}
253
-
254
-		/**
255
-		 * Save Changes Hook. What to do when changes are saved
256
-		 *
257
-		 * @param array $saved_options Saved data.
258
-		 * @param array $old_options   Previous data.
259
-		 *
260
-		 * @return      array
261
-		 * @since       1.0.0
262
-		 * @access      public
263
-		 */
264
-		public function save_hook( array $saved_options = array(), array $old_options = array() ): array {
265
-			if ( ! isset( $saved_options[ $this->field_id ] ) || empty( $saved_options[ $this->field_id ] ) || ( is_array( $saved_options[ $this->field_id ] ) && $old_options === $saved_options ) || ! array_key_exists( $this->field_id, $saved_options ) ) {
266
-				return $saved_options;
267
-			}
268
-
269
-			// We'll use the reset hook instead.
270
-			if ( ! empty( $saved_options['defaults'] ) || ! empty( $saved_options['defaults-section'] ) ) {
271
-				return $saved_options;
272
-			}
273
-
274
-			$first_value = reset( $saved_options[ $this->field_id ] ); // First Element's Value.
275
-
276
-			// Parse the JSON to an array.
277
-			if ( isset( $first_value['data'] ) ) {
278
-
279
-				Redux_Color_Scheme_Functions::$parent   = $this->parent;
280
-				Redux_Color_Scheme_Functions::$field_id = $this->field_id;
281
-
282
-				Redux_Color_Scheme_Functions::set_current_scheme_id( $saved_options['redux-scheme-select'] );
283
-
284
-				// Get the current field ID.
285
-				$raw_data = $saved_options[ $this->field_id ];
286
-
287
-				// Create a new array.
288
-				$save_data = array();
289
-
290
-				// Enum through saved data.
291
-				foreach ( $raw_data as $id => $val ) {
292
-
293
-					if ( 'color_scheme_name' !== $id ) {
294
-						if ( is_array( $val ) ) {
295
-
296
-							if ( ! isset( $val['data'] ) ) {
297
-								continue;
298
-							}
299
-
300
-							$data = json_decode( rawurldecode( $val['data'] ), true );
301
-
302
-							// Sanitize everything.
303
-							$color = $data['color'] ?? '';
304
-							$alpha = $data['alpha'] ?? 1;
305
-
306
-							$id    = $data['id'] ?? $id;
307
-							$title = $data['title'] ?? $id;
308
-
309
-							$grp = $data['group'] ?? '';
310
-
311
-							if ( '' === $color || 'transparent' === $color ) {
312
-								$rgba = $this->output_transparent ? 'transparent' : '';
313
-							} else {
314
-								$rgba = Redux_Helpers::hex2rgba( $color, $alpha );
315
-							}
316
-
317
-							// Create an array of saved data.
318
-							$save_data[] = array(
319
-								'id'    => $id,
320
-								'title' => $title,
321
-								'color' => $color,
322
-								'alpha' => $alpha,
323
-								'group' => $grp,
324
-								'rgba'  => $rgba,
325
-							);
326
-						} else {
327
-							$save_data[] = array(
328
-								'id'    => $id,
329
-								'value' => $val,
330
-								'type'  => 'select',
331
-							);
332
-						}
333
-					}
334
-				}
335
-
336
-				$new_scheme = array();
337
-
338
-				$new_scheme['color_scheme_name'] = Redux_Color_Scheme_Functions::get_current_scheme_id();
339
-
340
-				// Enum through values and assign them to a new array.
341
-				foreach ( $save_data as $val ) {
342
-					if ( isset( $val['id'] ) ) {
343
-						$new_scheme[ $val['id'] ] = $val;
344
-					}
345
-				}
346
-
347
-				// Filter for DB save
348
-				// Doesn't need to save select arrays to a database,
349
-				// just the id => value.
350
-				$database_data = $new_scheme;
351
-
352
-				foreach ( $database_data as $k => $v ) {
353
-					if ( isset( $v['type'] ) ) {
354
-						$val = $v['value'];
355
-
356
-						unset( $database_data[ $k ] );
357
-
358
-						$database_data[ $k ] = $val;
359
-					}
360
-				}
361
-
362
-				$saved_options[ $this->field_id ] = $database_data;
363
-
364
-				// Check if we should save this compared to the old data.
365
-				$save_scheme = false;
366
-
367
-				// Doesn't exist or is empty.
368
-				if ( ! isset( $old_options[ $this->field_id ] ) || ( isset( $old_options[ $this->field_id ] ) && ! empty( $old_options[ $this->field_id ] ) ) ) {
369
-					$save_scheme = true;
370
-				}
371
-
372
-				// Isn't empty and isn't the same as the new array.
373
-				if ( ! empty( $old_options[ $this->field_id ] ) && $saved_options[ $this->field_id ] !== $old_options[ $this->field_id ] ) {
374
-					$save_scheme = true;
375
-				}
376
-
377
-				if ( $save_scheme ) {
378
-					$scheme = Redux_Color_Scheme_Functions::get_current_scheme_id();
379
-					Redux_Color_Scheme_Functions::set_scheme_data( $scheme, $save_data );
380
-				}
381
-			}
382
-
383
-			return $saved_options;
384
-		}
385
-
386
-		/**
387
-		 * Reset data. Restores colour picker to default values
388
-		 *
389
-		 * @since       1.0.0
390
-		 * @access      private
391
-		 * @return      void
392
-		 */
393
-		private function reset_data() {
394
-			Redux_Color_Scheme_Functions::$parent   = $this->parent;
395
-			Redux_Color_Scheme_Functions::$field_id = $this->field_id;
396
-
397
-			// Get default data.
398
-			$data = $this->get_default_data();
399
-
400
-			// Add to (and/or create) JSON scheme file.
401
-			Redux_Color_Scheme_Functions::set_scheme_data( 'Default', $data );
402
-
403
-			// Set default scheme.
404
-			Redux_Color_Scheme_Functions::set_current_scheme_id( 'Default' );
405
-		}
406
-
407
-		/**
408
-		 * Reset All Hook. Todo list when all data is reset
409
-		 *
410
-		 * @return      void
411
-		 * @since       1.0.0
412
-		 * @access      public
413
-		 */
414
-		public function reset_all() {
415
-			if ( ! empty( $this->field_id ) && isset( $this->parent->options_defaults[ $this->field_id ] ) && ! empty( $this->parent->options_defaults[ $this->field_id ] ) ) {
416
-				Redux_Color_Scheme_Functions::$parent   = $this->parent;
417
-				Redux_Color_Scheme_Functions::$field_id = $this->field_id;
418
-
419
-				$this->reset_data();
420
-			}
421
-		}
422
-
423
-		/**
424
-		 * AJAX evaluator. Determine course of action based on AJAX callback
425
-		 *
426
-		 * @since       1.0.0
427
-		 * @access      public
428
-		 * @return      void
429
-		 */
430
-		public function parse_ajax() {
431
-			if ( ! is_user_logged_in() && ! is_admin() && ! current_user_can( $this->parent->args['page_permissions'] ) ) {
432
-				wp_die( esc_html__( 'You do not have permission to perform this action.', 'redux-framework' ) );
433
-			}
434
-
435
-			$opt_name = $this->parent->args['opt_name'];
436
-			$parent   = $this->parent;
437
-
438
-			$nonce = isset( $_REQUEST['nonce'] ) ? sanitize_key( wp_unslash( $_REQUEST['nonce'] ) ) : '';
439
-			if ( ! wp_verify_nonce( $nonce, 'redux_' . $opt_name . '_color_schemes' ) ) {
440
-				wp_die( esc_html__( 'Invalid Security Credentials. Please reload the page and try again.', 'redux-framework' ) );
441
-			}
442
-
443
-			$type = isset( $_REQUEST['type'] ) ? sanitize_key( wp_unslash( $_REQUEST['type'] ) ) : '';
444
-			if ( ! in_array( $type, array( 'save', 'delete', 'update', 'export', 'import' ), true ) ) {
445
-				wp_die( esc_html__( 'Invalid request.', 'redux-framework' ) );
446
-			}
447
-
448
-			if ( 'save' === $type ) {
449
-				$this->save_scheme( $parent );
450
-			} elseif ( 'delete' === $type ) {
451
-				$this->delete_scheme( $parent );
452
-			} elseif ( 'update' === $type ) {
453
-				$this->get_scheme_html( $parent );
454
-			} elseif ( 'export' === $type ) {
455
-				$this->download_schemes();
456
-			} elseif ( 'import' === $type ) {
457
-				$this->import_schemes();
458
-			}
459
-		}
460
-
461
-		/**
462
-		 * Download Scheme File.
463
-		 *
464
-		 * @since       4.4.18
465
-		 * @access      private
466
-		 * @return      void
467
-		 */
468
-		private function import_schemes() {
469
-			if ( isset( $_REQUEST['content'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
470
-				$opt_name = Redux_Color_Scheme_Functions::$parent->args['opt_name'];
471
-				if ( ! preg_match( '/^[a-zA-Z0-9_-]+$/', $opt_name ) ) {
472
-					$result = array(
473
-						'result' => false,
474
-						'data'   => esc_html__( 'Invalid opt_name', 'redux-framework' ),
475
-					);
476
-					echo wp_json_encode( $result );
477
-					die();
478
-				}
479
-
480
-				$field_id = Redux_Color_Scheme_Functions::$field_id;
481
-				if ( ! preg_match( '/^[a-zA-Z0-9_-]+$/', $field_id ) ) {
482
-					$result = array(
483
-						'result' => false,
484
-						'data'   => esc_html__( 'Invalid field_id', 'redux-framework' ),
485
-					);
486
-					echo wp_json_encode( $result );
487
-					die();
488
-				}
489
-
490
-				$content = wp_unslash( $_REQUEST['content'] ); // phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
491
-				$content = is_array( $content ) ? array_map( 'stripslashes_deep', $content ) : stripslashes( $content );
492
-				$content = json_decode( $content, true );
493
-
494
-				if ( is_null( $content ) ) {
495
-					$result = array(
496
-						'result' => false,
497
-						'data'   => esc_html__( 'Import unsuccessful! Malformed JSON data detected.', 'redux-framework' ),
498
-					);
499
-
500
-					$result = wp_json_encode( $result );
501
-
502
-					echo $result; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
503
-
504
-					die;
505
-				}
506
-
507
-				if ( isset( $content['Default']['color_scheme_name'] ) ) {
508
-					$content = wp_json_encode( $content );
509
-
510
-					$param_array = array(
511
-						'content'   => $content,
512
-						'overwrite' => true,
513
-						'chmod'     => FS_CHMOD_FILE,
514
-					);
515
-
516
-					$import_file = Redux_Color_Scheme_Functions::$upload_dir . sanitize_file_name( $opt_name ) . '_' . sanitize_file_name( $field_id ) . '.json';
517
-
518
-					if ( true === Redux_Core::$filesystem->execute( 'put_contents', $import_file, $param_array ) ) {
519
-						$result = array(
520
-							'result' => true,
521
-							// translators: %s = HTML content.
522
-							'data'   => sprintf( esc_html__( 'Import successful! Click %s to refresh.', 'redux-framework' ), '<strong>' . esc_html__( 'OK', 'redux-framework' ) . '</strong>' ),
523
-						);
524
-					} else {
525
-						$result = array(
526
-							'result' => false,
527
-							'data'   => esc_html__( 'Import unsuccessful! File permission error: Could not write import data to server.', 'redux-framework' ),
528
-						);
529
-					}
530
-				} else {
531
-					$result = array(
532
-						'result' => false,
533
-						'data'   => esc_html__( 'Import unsuccessful! The selected file is not a valid color scheme file.', 'redux-framework' ),
534
-					);
535
-				}
536
-			} else {
537
-				$result = array(
538
-					'result' => false,
539
-					'data'   => esc_html__( 'Import unsuccessful! No data detected in the import file.', 'redux-framework' ),
540
-				);
541
-			}
542
-
543
-			$result = wp_json_encode( $result );
544
-
545
-			echo $result; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
546
-
547
-			die;
548
-		}
549
-
550
-		/**
551
-		 * Download Scheme File.
552
-		 *
553
-		 * @since       1.0.0
554
-		 * @access      private
555
-		 * @return      void
556
-		 */
557
-		private function download_schemes() {
558
-			if ( ! Redux_Rate_Limiter::check( 'color_schemes' ) ) {
559
-				wp_die( 'Rate limit exceeded. Please try again later.' );
560
-			}
561
-
562
-			Redux_Color_Scheme_Functions::$parent   = $this->parent;
563
-			Redux_Color_Scheme_Functions::$field_id = $this->field_id;
564
-
565
-			// Read the contents of the scheme file.
566
-			$content = Redux_Color_Scheme_Functions::read_scheme_file();
567
-			$content = wp_json_encode( $content );
568
-
569
-			// Set header info.
570
-			header( 'Content-Description: File Transfer' );
571
-			header( 'Content-type: application/txt' );
572
-			header( 'Content-Disposition: attachment; filename="redux_schemes_' . $this->parent->args['opt_name'] . '_' . $this->field_id . '_' . gmdate( 'm-d-Y' ) . '.json"' );
573
-			header( 'Content-Transfer-Encoding: binary' );
574
-			header( 'Expires: 0' );
575
-			header( 'Cache-Control: must-revalidate' );
576
-			header( 'Pragma: public' );
577
-
578
-			// File download.
579
-			echo $content; // phpcs:ignore WordPress.Security.EscapeOutput
580
-
581
-			// 2B ~! 2B
582
-			die;
583
-		}
584
-
585
-		/**
586
-		 * Save Scheme. Saved an individual scheme to JSON scheme file.
587
-		 *
588
-		 * @param ReduxFramework $redux ReduxFramework object.
589
-		 *
590
-		 * @return      void
591
-		 * @since       1.0.0
592
-		 * @access      private
593
-		 */
594
-		private function save_scheme( ReduxFramework $redux ) {
595
-			Redux_Color_Scheme_Functions::$parent   = $redux;
596
-			Redux_Color_Scheme_Functions::$field_id = $this->field_id;
597
-
598
-			// Get the scheme name.
599
-			if ( isset( $_REQUEST['scheme_name'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
600
-				$scheme_name = sanitize_text_field( wp_unslash( $_REQUEST['scheme_name'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
601
-
602
-				// Check for duplicates.
603
-				$names = Redux_Color_Scheme_Functions::get_scheme_names();
604
-				foreach ( $names as $name ) {
605
-					$name     = strtolower( $name );
606
-					$tmp_name = strtolower( $scheme_name );
607
-
608
-					if ( $name === $tmp_name ) {
609
-						echo 'fail';
610
-						die();
611
-					}
612
-				}
613
-
614
-				// Get scheme data.
615
-				if ( isset( $_REQUEST['scheme_data'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
616
-					$scheme_data = wp_unslash( $_REQUEST['scheme_data'] ); // phpcs:ignore WordPress.Security
617
-
618
-					// Get field ID.
619
-					if ( isset( $_REQUEST['field_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
620
-						$scheme_data = rawurldecode( $scheme_data );
621
-						$scheme_data = json_decode( $scheme_data, true );
622
-
623
-						// Save scheme to file.  If successful...
624
-						if ( true === Redux_Color_Scheme_Functions::set_scheme_data( $scheme_name, $scheme_data ) ) {
625
-
626
-							// Update scheme selector.
627
-							echo Redux_Color_Scheme_Functions::get_scheme_select_html( $scheme_name ); // phpcs:ignore WordPress.Security.EscapeOutput
628
-						}
629
-					}
630
-				}
631
-			}
632
-
633
-			die(); // a horrible death!
634
-		}
635
-
636
-		/**
637
-		 * Delete Scheme. Delete individual scheme from JSON scheme file.
638
-		 *
639
-		 * @param ReduxFramework $redux ReduxFramework object.
640
-		 *
641
-		 * @return      void
642
-		 * @since       1.0.0
643
-		 * @access      private
644
-		 */
645
-		private function delete_scheme( ReduxFramework $redux ) {
646
-
647
-			// Get deleted scheme ID.
648
-			if ( isset( $_REQUEST['scheme_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
649
-				$scheme_id = sanitize_text_field( wp_unslash( $_REQUEST['scheme_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
650
-
651
-				// Get field ID.
652
-				if ( isset( $_REQUEST['field_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
653
-					$field_id = sanitize_text_field( wp_unslash( $_REQUEST['field_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
654
-
655
-					// If scheme ID was passed (and why wouldn't it be?? Hmm??).
656
-					if ( $scheme_id ) {
657
-						Redux_Color_Scheme_Functions::$field_id = $field_id;
658
-						Redux_Color_Scheme_Functions::$parent   = $redux;
659
-
660
-						// Get the entire scheme file.
661
-						$schemes = Redux_Color_Scheme_Functions::read_scheme_file();
662
-
663
-						// If we got a good read...
664
-						if ( false !== $schemes ) {
665
-
666
-							// If scheme name exists...
667
-							if ( isset( $schemes[ $scheme_id ] ) ) {
668
-
669
-								// Unset it.
670
-								unset( $schemes[ $scheme_id ] );
671
-
672
-								// Save the scheme data, minus the deleted scheme.  Upon success...
673
-								if ( true === Redux_Color_Scheme_Functions::write_scheme_file( $schemes ) ) {
674
-
675
-									// Set default scheme.
676
-									Redux_Color_Scheme_Functions::set_current_scheme_id( 'Default' );
677
-
678
-									// Update field ID.
679
-									Redux_Color_Scheme_Functions::$field_id = $field_id;
680
-
681
-									// Meh TODO.
682
-									Redux_Color_Scheme_Functions::set_database_data();
683
-
684
-									echo 'success';
685
-								} else {
686
-									echo 'Failed to write JSON file to server.';
687
-								}
688
-							} else {
689
-								echo 'Scheme name does not exist in JSON string.  Aborting.';
690
-							}
691
-						} else {
692
-							echo 'Failed to read JSON scheme file, or file is empty.';
693
-						}
694
-					} else {
695
-						echo 'No scheme ID passed.  Aborting.';
696
-					}
697
-				}
698
-			}
699
-
700
-			die(); // rolled a two.
701
-		}
702
-
703
-		/**
704
-		 * Gets the new scheme based on selection.
705
-		 *
706
-		 * @param ReduxFramework $redux ReduxFramework object.
707
-		 *
708
-		 * @return      void
709
-		 * @since       1.0.0
710
-		 * @access      private
711
-		 */
712
-		private function get_scheme_html( ReduxFramework $redux ) {
713
-			if ( isset( $_POST['scheme_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
714
-
715
-				// Get the selected scheme name.
716
-				$scheme_id = sanitize_text_field( wp_unslash( $_POST['scheme_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
717
-
718
-				if ( isset( $_POST['field_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
719
-
720
-					// Get the field ID.
721
-					$field_id = sanitize_text_field( wp_unslash( $_POST['field_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
722
-
723
-					// Get the field class.
724
-					$field_class = isset( $_POST['field_class'] ) ? sanitize_text_field( wp_unslash( $_POST['field_class'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
725
-
726
-					Redux_Color_Scheme_Functions::$parent = $redux;
727
-
728
-					// Set the updated field ID.
729
-					Redux_Color_Scheme_Functions::$field_id = $field_id;
730
-
731
-					// Set the updated field class.
732
-					Redux_Color_Scheme_Functions::$field_class = $field_class;
733
-
734
-					// Get the color picket layout HTML.
735
-					$html = Redux_Color_Scheme_Functions::get_current_color_scheme_html( $scheme_id );
736
-
737
-					// Print!
738
-					echo $html; // phpcs:ignore WordPress.Security.EscapeOutput
739
-				}
740
-			}
741
-
742
-			die(); // another day.
743
-		}
744
-
745
-
746
-		/**
747
-		 * Retrieves an array of default data for color picker.
748
-		 *
749
-		 * @since       1.0.0
750
-		 * @access      private
751
-		 * @return      array Default values from config.
752
-		 */
753
-		private function get_default_data(): array {
754
-			$def_opts = $this->parent->options_defaults[ $this->field_id ];
755
-
756
-			if ( isset( $def_opts['color_scheme_name'] ) ) {
757
-				return array();
758
-			}
759
-
760
-			$sections = $this->parent->sections;
761
-			$data     = array();
762
-
763
-			foreach ( $sections as $arr ) {
764
-				if ( isset( $arr['fields'] ) ) {
765
-					foreach ( $arr['fields'] as $arr2 ) {
766
-						if ( $arr2['id'] === $this->field_id ) {
767
-
768
-							// Select fields.
769
-							if ( isset( $arr2['select'] ) ) {
770
-								foreach ( $arr2['select'] as $v ) {
771
-									$data[] = array(
772
-										'id'    => $v['id'],
773
-										'value' => $v['default'],
774
-										'type'  => 'select',
775
-									);
776
-								}
777
-							}
778
-						}
779
-					}
780
-				}
781
-			}
782
-
783
-			foreach ( $def_opts as $v ) {
784
-				$title = $v['title'] ?? $v['id'];
785
-				$color = $v['color'] ?? '';
786
-				$alpha = $v['alpha'] ?? 1;
787
-				$grp   = $v['group'] ?? '';
788
-
789
-				if ( '' === $color || 'transparent' === $color ) {
790
-					$rgba = $this->output_transparent ? 'transparent' : '';
791
-				} else {
792
-					$rgba = Redux_Helpers::hex2rgba( $color, $alpha );
793
-				}
794
-
795
-				$data[] = array(
796
-					'id'    => $v['id'],
797
-					'title' => $title,
798
-					'color' => $color,
799
-					'alpha' => $alpha,
800
-					'group' => $grp,
801
-					'rgba'  => $rgba,
802
-				);
803
-			}
804
-
805
-			return $data;
806
-		}
807
-	}
808
-
809
-	class_alias( Redux_Extension_Color_Scheme::class, 'ReduxFramework_Extension_Color_Scheme' );
225
+        /**
226
+         * Reset section defaults.
227
+         *
228
+         * @param array $defaults Default values.
229
+         *
230
+         * @return array
231
+         */
232
+        public function reset_defaults_section( array $defaults = array() ): array {
233
+            if ( Redux_Helpers::is_field_in_use( $this->parent, 'color_scheme' ) ) {
234
+                // Get the current tab/section number.
235
+                if ( isset( $_COOKIE['redux_current_tab'] ) ) {
236
+                    $cur_tab = sanitize_text_field( wp_unslash( $_COOKIE['redux_current_tab'] ) );
237
+
238
+                    // Get the tab/section number field is used on.
239
+                    $tab_num = $this->parent->field_sections['color_scheme'][ $this->field_id ];
240
+
241
+                    // Match...
242
+                    if ( $cur_tab === $tab_num ) {
243
+
244
+                        // Reset data.
245
+                        $this->reset_all();
246
+                    }
247
+                    $defaults[ $this->field_id ] = Redux_Color_Scheme_Functions::data_array_from_scheme( 'Default' );
248
+                }
249
+            }
250
+
251
+            return $defaults;
252
+        }
253
+
254
+        /**
255
+         * Save Changes Hook. What to do when changes are saved
256
+         *
257
+         * @param array $saved_options Saved data.
258
+         * @param array $old_options   Previous data.
259
+         *
260
+         * @return      array
261
+         * @since       1.0.0
262
+         * @access      public
263
+         */
264
+        public function save_hook( array $saved_options = array(), array $old_options = array() ): array {
265
+            if ( ! isset( $saved_options[ $this->field_id ] ) || empty( $saved_options[ $this->field_id ] ) || ( is_array( $saved_options[ $this->field_id ] ) && $old_options === $saved_options ) || ! array_key_exists( $this->field_id, $saved_options ) ) {
266
+                return $saved_options;
267
+            }
268
+
269
+            // We'll use the reset hook instead.
270
+            if ( ! empty( $saved_options['defaults'] ) || ! empty( $saved_options['defaults-section'] ) ) {
271
+                return $saved_options;
272
+            }
273
+
274
+            $first_value = reset( $saved_options[ $this->field_id ] ); // First Element's Value.
275
+
276
+            // Parse the JSON to an array.
277
+            if ( isset( $first_value['data'] ) ) {
278
+
279
+                Redux_Color_Scheme_Functions::$parent   = $this->parent;
280
+                Redux_Color_Scheme_Functions::$field_id = $this->field_id;
281
+
282
+                Redux_Color_Scheme_Functions::set_current_scheme_id( $saved_options['redux-scheme-select'] );
283
+
284
+                // Get the current field ID.
285
+                $raw_data = $saved_options[ $this->field_id ];
286
+
287
+                // Create a new array.
288
+                $save_data = array();
289
+
290
+                // Enum through saved data.
291
+                foreach ( $raw_data as $id => $val ) {
292
+
293
+                    if ( 'color_scheme_name' !== $id ) {
294
+                        if ( is_array( $val ) ) {
295
+
296
+                            if ( ! isset( $val['data'] ) ) {
297
+                                continue;
298
+                            }
299
+
300
+                            $data = json_decode( rawurldecode( $val['data'] ), true );
301
+
302
+                            // Sanitize everything.
303
+                            $color = $data['color'] ?? '';
304
+                            $alpha = $data['alpha'] ?? 1;
305
+
306
+                            $id    = $data['id'] ?? $id;
307
+                            $title = $data['title'] ?? $id;
308
+
309
+                            $grp = $data['group'] ?? '';
310
+
311
+                            if ( '' === $color || 'transparent' === $color ) {
312
+                                $rgba = $this->output_transparent ? 'transparent' : '';
313
+                            } else {
314
+                                $rgba = Redux_Helpers::hex2rgba( $color, $alpha );
315
+                            }
316
+
317
+                            // Create an array of saved data.
318
+                            $save_data[] = array(
319
+                                'id'    => $id,
320
+                                'title' => $title,
321
+                                'color' => $color,
322
+                                'alpha' => $alpha,
323
+                                'group' => $grp,
324
+                                'rgba'  => $rgba,
325
+                            );
326
+                        } else {
327
+                            $save_data[] = array(
328
+                                'id'    => $id,
329
+                                'value' => $val,
330
+                                'type'  => 'select',
331
+                            );
332
+                        }
333
+                    }
334
+                }
335
+
336
+                $new_scheme = array();
337
+
338
+                $new_scheme['color_scheme_name'] = Redux_Color_Scheme_Functions::get_current_scheme_id();
339
+
340
+                // Enum through values and assign them to a new array.
341
+                foreach ( $save_data as $val ) {
342
+                    if ( isset( $val['id'] ) ) {
343
+                        $new_scheme[ $val['id'] ] = $val;
344
+                    }
345
+                }
346
+
347
+                // Filter for DB save
348
+                // Doesn't need to save select arrays to a database,
349
+                // just the id => value.
350
+                $database_data = $new_scheme;
351
+
352
+                foreach ( $database_data as $k => $v ) {
353
+                    if ( isset( $v['type'] ) ) {
354
+                        $val = $v['value'];
355
+
356
+                        unset( $database_data[ $k ] );
357
+
358
+                        $database_data[ $k ] = $val;
359
+                    }
360
+                }
361
+
362
+                $saved_options[ $this->field_id ] = $database_data;
363
+
364
+                // Check if we should save this compared to the old data.
365
+                $save_scheme = false;
366
+
367
+                // Doesn't exist or is empty.
368
+                if ( ! isset( $old_options[ $this->field_id ] ) || ( isset( $old_options[ $this->field_id ] ) && ! empty( $old_options[ $this->field_id ] ) ) ) {
369
+                    $save_scheme = true;
370
+                }
371
+
372
+                // Isn't empty and isn't the same as the new array.
373
+                if ( ! empty( $old_options[ $this->field_id ] ) && $saved_options[ $this->field_id ] !== $old_options[ $this->field_id ] ) {
374
+                    $save_scheme = true;
375
+                }
376
+
377
+                if ( $save_scheme ) {
378
+                    $scheme = Redux_Color_Scheme_Functions::get_current_scheme_id();
379
+                    Redux_Color_Scheme_Functions::set_scheme_data( $scheme, $save_data );
380
+                }
381
+            }
382
+
383
+            return $saved_options;
384
+        }
385
+
386
+        /**
387
+         * Reset data. Restores colour picker to default values
388
+         *
389
+         * @since       1.0.0
390
+         * @access      private
391
+         * @return      void
392
+         */
393
+        private function reset_data() {
394
+            Redux_Color_Scheme_Functions::$parent   = $this->parent;
395
+            Redux_Color_Scheme_Functions::$field_id = $this->field_id;
396
+
397
+            // Get default data.
398
+            $data = $this->get_default_data();
399
+
400
+            // Add to (and/or create) JSON scheme file.
401
+            Redux_Color_Scheme_Functions::set_scheme_data( 'Default', $data );
402
+
403
+            // Set default scheme.
404
+            Redux_Color_Scheme_Functions::set_current_scheme_id( 'Default' );
405
+        }
406
+
407
+        /**
408
+         * Reset All Hook. Todo list when all data is reset
409
+         *
410
+         * @return      void
411
+         * @since       1.0.0
412
+         * @access      public
413
+         */
414
+        public function reset_all() {
415
+            if ( ! empty( $this->field_id ) && isset( $this->parent->options_defaults[ $this->field_id ] ) && ! empty( $this->parent->options_defaults[ $this->field_id ] ) ) {
416
+                Redux_Color_Scheme_Functions::$parent   = $this->parent;
417
+                Redux_Color_Scheme_Functions::$field_id = $this->field_id;
418
+
419
+                $this->reset_data();
420
+            }
421
+        }
422
+
423
+        /**
424
+         * AJAX evaluator. Determine course of action based on AJAX callback
425
+         *
426
+         * @since       1.0.0
427
+         * @access      public
428
+         * @return      void
429
+         */
430
+        public function parse_ajax() {
431
+            if ( ! is_user_logged_in() && ! is_admin() && ! current_user_can( $this->parent->args['page_permissions'] ) ) {
432
+                wp_die( esc_html__( 'You do not have permission to perform this action.', 'redux-framework' ) );
433
+            }
434
+
435
+            $opt_name = $this->parent->args['opt_name'];
436
+            $parent   = $this->parent;
437
+
438
+            $nonce = isset( $_REQUEST['nonce'] ) ? sanitize_key( wp_unslash( $_REQUEST['nonce'] ) ) : '';
439
+            if ( ! wp_verify_nonce( $nonce, 'redux_' . $opt_name . '_color_schemes' ) ) {
440
+                wp_die( esc_html__( 'Invalid Security Credentials. Please reload the page and try again.', 'redux-framework' ) );
441
+            }
442
+
443
+            $type = isset( $_REQUEST['type'] ) ? sanitize_key( wp_unslash( $_REQUEST['type'] ) ) : '';
444
+            if ( ! in_array( $type, array( 'save', 'delete', 'update', 'export', 'import' ), true ) ) {
445
+                wp_die( esc_html__( 'Invalid request.', 'redux-framework' ) );
446
+            }
447
+
448
+            if ( 'save' === $type ) {
449
+                $this->save_scheme( $parent );
450
+            } elseif ( 'delete' === $type ) {
451
+                $this->delete_scheme( $parent );
452
+            } elseif ( 'update' === $type ) {
453
+                $this->get_scheme_html( $parent );
454
+            } elseif ( 'export' === $type ) {
455
+                $this->download_schemes();
456
+            } elseif ( 'import' === $type ) {
457
+                $this->import_schemes();
458
+            }
459
+        }
460
+
461
+        /**
462
+         * Download Scheme File.
463
+         *
464
+         * @since       4.4.18
465
+         * @access      private
466
+         * @return      void
467
+         */
468
+        private function import_schemes() {
469
+            if ( isset( $_REQUEST['content'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
470
+                $opt_name = Redux_Color_Scheme_Functions::$parent->args['opt_name'];
471
+                if ( ! preg_match( '/^[a-zA-Z0-9_-]+$/', $opt_name ) ) {
472
+                    $result = array(
473
+                        'result' => false,
474
+                        'data'   => esc_html__( 'Invalid opt_name', 'redux-framework' ),
475
+                    );
476
+                    echo wp_json_encode( $result );
477
+                    die();
478
+                }
479
+
480
+                $field_id = Redux_Color_Scheme_Functions::$field_id;
481
+                if ( ! preg_match( '/^[a-zA-Z0-9_-]+$/', $field_id ) ) {
482
+                    $result = array(
483
+                        'result' => false,
484
+                        'data'   => esc_html__( 'Invalid field_id', 'redux-framework' ),
485
+                    );
486
+                    echo wp_json_encode( $result );
487
+                    die();
488
+                }
489
+
490
+                $content = wp_unslash( $_REQUEST['content'] ); // phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
491
+                $content = is_array( $content ) ? array_map( 'stripslashes_deep', $content ) : stripslashes( $content );
492
+                $content = json_decode( $content, true );
493
+
494
+                if ( is_null( $content ) ) {
495
+                    $result = array(
496
+                        'result' => false,
497
+                        'data'   => esc_html__( 'Import unsuccessful! Malformed JSON data detected.', 'redux-framework' ),
498
+                    );
499
+
500
+                    $result = wp_json_encode( $result );
501
+
502
+                    echo $result; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
503
+
504
+                    die;
505
+                }
506
+
507
+                if ( isset( $content['Default']['color_scheme_name'] ) ) {
508
+                    $content = wp_json_encode( $content );
509
+
510
+                    $param_array = array(
511
+                        'content'   => $content,
512
+                        'overwrite' => true,
513
+                        'chmod'     => FS_CHMOD_FILE,
514
+                    );
515
+
516
+                    $import_file = Redux_Color_Scheme_Functions::$upload_dir . sanitize_file_name( $opt_name ) . '_' . sanitize_file_name( $field_id ) . '.json';
517
+
518
+                    if ( true === Redux_Core::$filesystem->execute( 'put_contents', $import_file, $param_array ) ) {
519
+                        $result = array(
520
+                            'result' => true,
521
+                            // translators: %s = HTML content.
522
+                            'data'   => sprintf( esc_html__( 'Import successful! Click %s to refresh.', 'redux-framework' ), '<strong>' . esc_html__( 'OK', 'redux-framework' ) . '</strong>' ),
523
+                        );
524
+                    } else {
525
+                        $result = array(
526
+                            'result' => false,
527
+                            'data'   => esc_html__( 'Import unsuccessful! File permission error: Could not write import data to server.', 'redux-framework' ),
528
+                        );
529
+                    }
530
+                } else {
531
+                    $result = array(
532
+                        'result' => false,
533
+                        'data'   => esc_html__( 'Import unsuccessful! The selected file is not a valid color scheme file.', 'redux-framework' ),
534
+                    );
535
+                }
536
+            } else {
537
+                $result = array(
538
+                    'result' => false,
539
+                    'data'   => esc_html__( 'Import unsuccessful! No data detected in the import file.', 'redux-framework' ),
540
+                );
541
+            }
542
+
543
+            $result = wp_json_encode( $result );
544
+
545
+            echo $result; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
546
+
547
+            die;
548
+        }
549
+
550
+        /**
551
+         * Download Scheme File.
552
+         *
553
+         * @since       1.0.0
554
+         * @access      private
555
+         * @return      void
556
+         */
557
+        private function download_schemes() {
558
+            if ( ! Redux_Rate_Limiter::check( 'color_schemes' ) ) {
559
+                wp_die( 'Rate limit exceeded. Please try again later.' );
560
+            }
561
+
562
+            Redux_Color_Scheme_Functions::$parent   = $this->parent;
563
+            Redux_Color_Scheme_Functions::$field_id = $this->field_id;
564
+
565
+            // Read the contents of the scheme file.
566
+            $content = Redux_Color_Scheme_Functions::read_scheme_file();
567
+            $content = wp_json_encode( $content );
568
+
569
+            // Set header info.
570
+            header( 'Content-Description: File Transfer' );
571
+            header( 'Content-type: application/txt' );
572
+            header( 'Content-Disposition: attachment; filename="redux_schemes_' . $this->parent->args['opt_name'] . '_' . $this->field_id . '_' . gmdate( 'm-d-Y' ) . '.json"' );
573
+            header( 'Content-Transfer-Encoding: binary' );
574
+            header( 'Expires: 0' );
575
+            header( 'Cache-Control: must-revalidate' );
576
+            header( 'Pragma: public' );
577
+
578
+            // File download.
579
+            echo $content; // phpcs:ignore WordPress.Security.EscapeOutput
580
+
581
+            // 2B ~! 2B
582
+            die;
583
+        }
584
+
585
+        /**
586
+         * Save Scheme. Saved an individual scheme to JSON scheme file.
587
+         *
588
+         * @param ReduxFramework $redux ReduxFramework object.
589
+         *
590
+         * @return      void
591
+         * @since       1.0.0
592
+         * @access      private
593
+         */
594
+        private function save_scheme( ReduxFramework $redux ) {
595
+            Redux_Color_Scheme_Functions::$parent   = $redux;
596
+            Redux_Color_Scheme_Functions::$field_id = $this->field_id;
597
+
598
+            // Get the scheme name.
599
+            if ( isset( $_REQUEST['scheme_name'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
600
+                $scheme_name = sanitize_text_field( wp_unslash( $_REQUEST['scheme_name'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
601
+
602
+                // Check for duplicates.
603
+                $names = Redux_Color_Scheme_Functions::get_scheme_names();
604
+                foreach ( $names as $name ) {
605
+                    $name     = strtolower( $name );
606
+                    $tmp_name = strtolower( $scheme_name );
607
+
608
+                    if ( $name === $tmp_name ) {
609
+                        echo 'fail';
610
+                        die();
611
+                    }
612
+                }
613
+
614
+                // Get scheme data.
615
+                if ( isset( $_REQUEST['scheme_data'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
616
+                    $scheme_data = wp_unslash( $_REQUEST['scheme_data'] ); // phpcs:ignore WordPress.Security
617
+
618
+                    // Get field ID.
619
+                    if ( isset( $_REQUEST['field_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
620
+                        $scheme_data = rawurldecode( $scheme_data );
621
+                        $scheme_data = json_decode( $scheme_data, true );
622
+
623
+                        // Save scheme to file.  If successful...
624
+                        if ( true === Redux_Color_Scheme_Functions::set_scheme_data( $scheme_name, $scheme_data ) ) {
625
+
626
+                            // Update scheme selector.
627
+                            echo Redux_Color_Scheme_Functions::get_scheme_select_html( $scheme_name ); // phpcs:ignore WordPress.Security.EscapeOutput
628
+                        }
629
+                    }
630
+                }
631
+            }
632
+
633
+            die(); // a horrible death!
634
+        }
635
+
636
+        /**
637
+         * Delete Scheme. Delete individual scheme from JSON scheme file.
638
+         *
639
+         * @param ReduxFramework $redux ReduxFramework object.
640
+         *
641
+         * @return      void
642
+         * @since       1.0.0
643
+         * @access      private
644
+         */
645
+        private function delete_scheme( ReduxFramework $redux ) {
646
+
647
+            // Get deleted scheme ID.
648
+            if ( isset( $_REQUEST['scheme_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
649
+                $scheme_id = sanitize_text_field( wp_unslash( $_REQUEST['scheme_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
650
+
651
+                // Get field ID.
652
+                if ( isset( $_REQUEST['field_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
653
+                    $field_id = sanitize_text_field( wp_unslash( $_REQUEST['field_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
654
+
655
+                    // If scheme ID was passed (and why wouldn't it be?? Hmm??).
656
+                    if ( $scheme_id ) {
657
+                        Redux_Color_Scheme_Functions::$field_id = $field_id;
658
+                        Redux_Color_Scheme_Functions::$parent   = $redux;
659
+
660
+                        // Get the entire scheme file.
661
+                        $schemes = Redux_Color_Scheme_Functions::read_scheme_file();
662
+
663
+                        // If we got a good read...
664
+                        if ( false !== $schemes ) {
665
+
666
+                            // If scheme name exists...
667
+                            if ( isset( $schemes[ $scheme_id ] ) ) {
668
+
669
+                                // Unset it.
670
+                                unset( $schemes[ $scheme_id ] );
671
+
672
+                                // Save the scheme data, minus the deleted scheme.  Upon success...
673
+                                if ( true === Redux_Color_Scheme_Functions::write_scheme_file( $schemes ) ) {
674
+
675
+                                    // Set default scheme.
676
+                                    Redux_Color_Scheme_Functions::set_current_scheme_id( 'Default' );
677
+
678
+                                    // Update field ID.
679
+                                    Redux_Color_Scheme_Functions::$field_id = $field_id;
680
+
681
+                                    // Meh TODO.
682
+                                    Redux_Color_Scheme_Functions::set_database_data();
683
+
684
+                                    echo 'success';
685
+                                } else {
686
+                                    echo 'Failed to write JSON file to server.';
687
+                                }
688
+                            } else {
689
+                                echo 'Scheme name does not exist in JSON string.  Aborting.';
690
+                            }
691
+                        } else {
692
+                            echo 'Failed to read JSON scheme file, or file is empty.';
693
+                        }
694
+                    } else {
695
+                        echo 'No scheme ID passed.  Aborting.';
696
+                    }
697
+                }
698
+            }
699
+
700
+            die(); // rolled a two.
701
+        }
702
+
703
+        /**
704
+         * Gets the new scheme based on selection.
705
+         *
706
+         * @param ReduxFramework $redux ReduxFramework object.
707
+         *
708
+         * @return      void
709
+         * @since       1.0.0
710
+         * @access      private
711
+         */
712
+        private function get_scheme_html( ReduxFramework $redux ) {
713
+            if ( isset( $_POST['scheme_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
714
+
715
+                // Get the selected scheme name.
716
+                $scheme_id = sanitize_text_field( wp_unslash( $_POST['scheme_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
717
+
718
+                if ( isset( $_POST['field_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
719
+
720
+                    // Get the field ID.
721
+                    $field_id = sanitize_text_field( wp_unslash( $_POST['field_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
722
+
723
+                    // Get the field class.
724
+                    $field_class = isset( $_POST['field_class'] ) ? sanitize_text_field( wp_unslash( $_POST['field_class'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
725
+
726
+                    Redux_Color_Scheme_Functions::$parent = $redux;
727
+
728
+                    // Set the updated field ID.
729
+                    Redux_Color_Scheme_Functions::$field_id = $field_id;
730
+
731
+                    // Set the updated field class.
732
+                    Redux_Color_Scheme_Functions::$field_class = $field_class;
733
+
734
+                    // Get the color picket layout HTML.
735
+                    $html = Redux_Color_Scheme_Functions::get_current_color_scheme_html( $scheme_id );
736
+
737
+                    // Print!
738
+                    echo $html; // phpcs:ignore WordPress.Security.EscapeOutput
739
+                }
740
+            }
741
+
742
+            die(); // another day.
743
+        }
744
+
745
+
746
+        /**
747
+         * Retrieves an array of default data for color picker.
748
+         *
749
+         * @since       1.0.0
750
+         * @access      private
751
+         * @return      array Default values from config.
752
+         */
753
+        private function get_default_data(): array {
754
+            $def_opts = $this->parent->options_defaults[ $this->field_id ];
755
+
756
+            if ( isset( $def_opts['color_scheme_name'] ) ) {
757
+                return array();
758
+            }
759
+
760
+            $sections = $this->parent->sections;
761
+            $data     = array();
762
+
763
+            foreach ( $sections as $arr ) {
764
+                if ( isset( $arr['fields'] ) ) {
765
+                    foreach ( $arr['fields'] as $arr2 ) {
766
+                        if ( $arr2['id'] === $this->field_id ) {
767
+
768
+                            // Select fields.
769
+                            if ( isset( $arr2['select'] ) ) {
770
+                                foreach ( $arr2['select'] as $v ) {
771
+                                    $data[] = array(
772
+                                        'id'    => $v['id'],
773
+                                        'value' => $v['default'],
774
+                                        'type'  => 'select',
775
+                                    );
776
+                                }
777
+                            }
778
+                        }
779
+                    }
780
+                }
781
+            }
782
+
783
+            foreach ( $def_opts as $v ) {
784
+                $title = $v['title'] ?? $v['id'];
785
+                $color = $v['color'] ?? '';
786
+                $alpha = $v['alpha'] ?? 1;
787
+                $grp   = $v['group'] ?? '';
788
+
789
+                if ( '' === $color || 'transparent' === $color ) {
790
+                    $rgba = $this->output_transparent ? 'transparent' : '';
791
+                } else {
792
+                    $rgba = Redux_Helpers::hex2rgba( $color, $alpha );
793
+                }
794
+
795
+                $data[] = array(
796
+                    'id'    => $v['id'],
797
+                    'title' => $title,
798
+                    'color' => $color,
799
+                    'alpha' => $alpha,
800
+                    'group' => $grp,
801
+                    'rgba'  => $rgba,
802
+                );
803
+            }
804
+
805
+            return $data;
806
+        }
807
+    }
808
+
809
+    class_alias( Redux_Extension_Color_Scheme::class, 'ReduxFramework_Extension_Color_Scheme' );
810 810
 }
Please login to merge, or discard this patch.
inc/extensions/import_export/class-redux-extension-import-export.php 1 patch
Indentation   +146 added lines, -146 removed lines patch added patch discarded remove patch
@@ -14,153 +14,153 @@
 block discarded – undo
14 14
 // Don't duplicate me!
15 15
 if ( ! class_exists( 'Redux_Extension_Import_Export', false ) ) {
16 16
 
17
-	/**
18
-	 * Main ReduxFramework import_export extension class
19
-	 *
20
-	 * @since       3.1.6
21
-	 */
22
-	class Redux_Extension_Import_Export extends Redux_Extension_Abstract {
23
-
24
-		/**
25
-		 * Ext version.
26
-		 *
27
-		 * @var string
28
-		 */
29
-		public static $version = '4.5.10';
30
-
31
-		/**
32
-		 * Is field bit.
33
-		 *
34
-		 * @var bool
35
-		 */
36
-		public bool $is_field = false;
37
-
38
-		/**
39
-		 * Class Constructor. Defines the args for the extensions class
40
-		 *
41
-		 * @param object $redux ReduxFramework object.
42
-		 *
43
-		 * @return      void
44
-		 * @since       1.0.0
45
-		 * @access      public
46
-		 */
47
-		public function __construct( $redux ) {
48
-			parent::__construct( $redux, __FILE__ );
49
-
50
-			$this->add_field( 'import_export' );
51
-
52
-			add_action( 'wp_ajax_redux_download_options-' . $this->parent->args['opt_name'], array( $this, 'download_options' ) );
53
-
54
-			// phpcs:ignore WordPress.NamingConventions.ValidHookName
55
-			do_action( 'redux/options/' . $this->parent->args['opt_name'] . '/import', array( $this, 'remove_cookie' ) );
56
-
57
-			$this->is_field = Redux_Helpers::is_field_in_use( $redux, 'import_export' );
58
-
59
-			if ( ! $this->is_field && $this->parent->args['show_import_export'] ) {
60
-				$this->add_section();
61
-			}
62
-
63
-			add_filter( 'upload_mimes', array( $this, 'custom_upload_mimes' ) );
64
-		}
65
-
66
-		/**
67
-		 * Adds the appropriate mime types to WordPress
68
-		 *
69
-		 * @param array|null $existing_mimes .
70
-		 *
71
-		 * @return array
72
-		 */
73
-		public function custom_upload_mimes( ?array $existing_mimes = array() ): array {
74
-			$existing_mimes['redux'] = 'application/redux';
75
-
76
-			return $existing_mimes;
77
-		}
78
-
79
-		/**
80
-		 * Add section to panel.
81
-		 */
82
-		public function add_section() {
83
-			$this->parent->sections[] = array(
84
-				'id'         => 'import/export',
85
-				'title'      => esc_html__( 'Import / Export', 'redux-framework' ),
86
-				'heading'    => '',
87
-				'icon'       => 'el el-refresh',
88
-				'customizer' => false,
89
-				'fields'     => array(
90
-					array(
91
-						'id'         => 'redux_import_export',
92
-						'type'       => 'import_export',
93
-						'full_width' => true,
94
-					),
95
-				),
96
-			);
97
-		}
98
-
99
-		/**
100
-		 * Import download options.
101
-		 */
102
-		public function download_options() {
103
-			if ( ! is_user_logged_in() && ! is_admin() && ! current_user_can( $this->parent->args['page_permissions'] ) ) {
104
-				wp_die( esc_html__( 'You do not have permission to export options.', 'redux-framework' ) );
105
-			}
106
-
107
-			if ( ! isset( $_GET['secret'] ) || ! wp_verify_nonce( sanitize_key( wp_unslash( $_GET['secret'] ) ), 'redux_io_' . $this->parent->args['opt_name'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
108
-				wp_die( 'Invalid secret for options use.' );
109
-			}
110
-
111
-			if ( ! Redux_Rate_Limiter::check( 'download_options' ) ) {
112
-				wp_die( 'Rate limit exceeded. Please try again later.' );
113
-			}
114
-
115
-			$this->parent->options_class->get();
116
-			$backup_options                 = $this->parent->options;
117
-			$backup_options['redux-backup'] = 1;
118
-
119
-			if ( isset( $backup_options['REDUX_imported'] ) ) {
120
-				unset( $backup_options['REDUX_imported'] );
121
-			}
122
-
123
-			// No need to escape this, as it's been properly escaped previously and through json_encode.
124
-			$content = wp_json_encode( $backup_options );
125
-
126
-			if ( isset( $_GET['action'] ) && 'redux_download_options-' . $this->parent->args['opt_name'] === $_GET['action'] ) { // phpcs:ignore WordPress.Security.NonceVerification
127
-				header( 'Content-Description: File Transfer' );
128
-				header( 'Content-type: application/txt' );
129
-				header( 'Content-Disposition: attachment; filename="redux_options_"' . $this->parent->args['opt_name'] . '_backup_' . gmdate( 'm-d-Y' ) . '.json' );
130
-				header( 'Content-Transfer-Encoding: binary' );
131
-				header( 'Expires: 0' );
132
-				header( 'Cache-Control: must-revalidate' );
133
-				header( 'Pragma: public' );
134
-			} else {
135
-				header( 'Expires: Mon, 26 Jul 1997 05:00:00 GMT' );
136
-				header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . 'GMT' );
137
-				header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
138
-				header( 'Cache-Control: no-store, no-cache, must-revalidate' );
139
-				header( 'Cache-Control: post-check=0, pre-check=0', false );
140
-				header( 'Pragma: no-cache' );
141
-
142
-				// Can't include the type. Thanks old Firefox and IE. BAH.
143
-				// header('Content-type: application/json');.
144
-			}
145
-
146
-			// phpcs:ignore WordPress.Security.EscapeOutput
147
-			echo( $content );
148
-			exit;
149
-		}
150
-
151
-		/**
152
-		 * Remove current tab cookie.
153
-		 */
154
-		public function remove_cookie() {
155
-			// Remove the import/export tab cookie.
156
-			if ( isset( $_COOKIE[ 'redux_current_tab_' . $this->parent->args['opt_name'] ] ) && 'import_export_default' === $_COOKIE[ 'redux_current_tab_' . $this->parent->args['opt_name'] ] ) {
157
-				setcookie( 'redux_current_tab_' . $this->parent->args['opt_name'], '', 1, '/' );
158
-				$_COOKIE[ 'redux_current_tab_' . $this->parent->args['opt_name'] ] = 1;
159
-			}
160
-		}
161
-	}
17
+    /**
18
+     * Main ReduxFramework import_export extension class
19
+     *
20
+     * @since       3.1.6
21
+     */
22
+    class Redux_Extension_Import_Export extends Redux_Extension_Abstract {
23
+
24
+        /**
25
+         * Ext version.
26
+         *
27
+         * @var string
28
+         */
29
+        public static $version = '4.5.10';
30
+
31
+        /**
32
+         * Is field bit.
33
+         *
34
+         * @var bool
35
+         */
36
+        public bool $is_field = false;
37
+
38
+        /**
39
+         * Class Constructor. Defines the args for the extensions class
40
+         *
41
+         * @param object $redux ReduxFramework object.
42
+         *
43
+         * @return      void
44
+         * @since       1.0.0
45
+         * @access      public
46
+         */
47
+        public function __construct( $redux ) {
48
+            parent::__construct( $redux, __FILE__ );
49
+
50
+            $this->add_field( 'import_export' );
51
+
52
+            add_action( 'wp_ajax_redux_download_options-' . $this->parent->args['opt_name'], array( $this, 'download_options' ) );
53
+
54
+            // phpcs:ignore WordPress.NamingConventions.ValidHookName
55
+            do_action( 'redux/options/' . $this->parent->args['opt_name'] . '/import', array( $this, 'remove_cookie' ) );
56
+
57
+            $this->is_field = Redux_Helpers::is_field_in_use( $redux, 'import_export' );
58
+
59
+            if ( ! $this->is_field && $this->parent->args['show_import_export'] ) {
60
+                $this->add_section();
61
+            }
62
+
63
+            add_filter( 'upload_mimes', array( $this, 'custom_upload_mimes' ) );
64
+        }
65
+
66
+        /**
67
+         * Adds the appropriate mime types to WordPress
68
+         *
69
+         * @param array|null $existing_mimes .
70
+         *
71
+         * @return array
72
+         */
73
+        public function custom_upload_mimes( ?array $existing_mimes = array() ): array {
74
+            $existing_mimes['redux'] = 'application/redux';
75
+
76
+            return $existing_mimes;
77
+        }
78
+
79
+        /**
80
+         * Add section to panel.
81
+         */
82
+        public function add_section() {
83
+            $this->parent->sections[] = array(
84
+                'id'         => 'import/export',
85
+                'title'      => esc_html__( 'Import / Export', 'redux-framework' ),
86
+                'heading'    => '',
87
+                'icon'       => 'el el-refresh',
88
+                'customizer' => false,
89
+                'fields'     => array(
90
+                    array(
91
+                        'id'         => 'redux_import_export',
92
+                        'type'       => 'import_export',
93
+                        'full_width' => true,
94
+                    ),
95
+                ),
96
+            );
97
+        }
98
+
99
+        /**
100
+         * Import download options.
101
+         */
102
+        public function download_options() {
103
+            if ( ! is_user_logged_in() && ! is_admin() && ! current_user_can( $this->parent->args['page_permissions'] ) ) {
104
+                wp_die( esc_html__( 'You do not have permission to export options.', 'redux-framework' ) );
105
+            }
106
+
107
+            if ( ! isset( $_GET['secret'] ) || ! wp_verify_nonce( sanitize_key( wp_unslash( $_GET['secret'] ) ), 'redux_io_' . $this->parent->args['opt_name'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
108
+                wp_die( 'Invalid secret for options use.' );
109
+            }
110
+
111
+            if ( ! Redux_Rate_Limiter::check( 'download_options' ) ) {
112
+                wp_die( 'Rate limit exceeded. Please try again later.' );
113
+            }
114
+
115
+            $this->parent->options_class->get();
116
+            $backup_options                 = $this->parent->options;
117
+            $backup_options['redux-backup'] = 1;
118
+
119
+            if ( isset( $backup_options['REDUX_imported'] ) ) {
120
+                unset( $backup_options['REDUX_imported'] );
121
+            }
122
+
123
+            // No need to escape this, as it's been properly escaped previously and through json_encode.
124
+            $content = wp_json_encode( $backup_options );
125
+
126
+            if ( isset( $_GET['action'] ) && 'redux_download_options-' . $this->parent->args['opt_name'] === $_GET['action'] ) { // phpcs:ignore WordPress.Security.NonceVerification
127
+                header( 'Content-Description: File Transfer' );
128
+                header( 'Content-type: application/txt' );
129
+                header( 'Content-Disposition: attachment; filename="redux_options_"' . $this->parent->args['opt_name'] . '_backup_' . gmdate( 'm-d-Y' ) . '.json' );
130
+                header( 'Content-Transfer-Encoding: binary' );
131
+                header( 'Expires: 0' );
132
+                header( 'Cache-Control: must-revalidate' );
133
+                header( 'Pragma: public' );
134
+            } else {
135
+                header( 'Expires: Mon, 26 Jul 1997 05:00:00 GMT' );
136
+                header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . 'GMT' );
137
+                header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
138
+                header( 'Cache-Control: no-store, no-cache, must-revalidate' );
139
+                header( 'Cache-Control: post-check=0, pre-check=0', false );
140
+                header( 'Pragma: no-cache' );
141
+
142
+                // Can't include the type. Thanks old Firefox and IE. BAH.
143
+                // header('Content-type: application/json');.
144
+            }
145
+
146
+            // phpcs:ignore WordPress.Security.EscapeOutput
147
+            echo( $content );
148
+            exit;
149
+        }
150
+
151
+        /**
152
+         * Remove current tab cookie.
153
+         */
154
+        public function remove_cookie() {
155
+            // Remove the import/export tab cookie.
156
+            if ( isset( $_COOKIE[ 'redux_current_tab_' . $this->parent->args['opt_name'] ] ) && 'import_export_default' === $_COOKIE[ 'redux_current_tab_' . $this->parent->args['opt_name'] ] ) {
157
+                setcookie( 'redux_current_tab_' . $this->parent->args['opt_name'], '', 1, '/' );
158
+                $_COOKIE[ 'redux_current_tab_' . $this->parent->args['opt_name'] ] = 1;
159
+            }
160
+        }
161
+    }
162 162
 }
163 163
 
164 164
 if ( ! class_exists( 'ReduxFramework_extension_import_export' ) ) {
165
-	class_alias( 'Redux_Extension_Import_Export', 'ReduxFramework_extension_import_export' );
165
+    class_alias( 'Redux_Extension_Import_Export', 'ReduxFramework_extension_import_export' );
166 166
 }
Please login to merge, or discard this patch.