PluginProbe ʕ •ᴥ•ʔ
Redux Framework / 4.5.6
Redux Framework v4.5.6
trunk 4.3.0 4.3.1 4.3.10 4.3.11 4.3.12 4.3.13 4.3.14 4.3.15 4.3.16 4.3.17 4.3.18 4.3.19 4.3.2 4.3.20 4.3.21 4.3.22 4.3.24 4.3.25 4.3.26 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.3.8 4.3.9 4.4.0 4.4.1 4.4.10 4.4.11 4.4.12 4.4.13 4.4.14 4.4.15 4.4.16 4.4.17 4.4.18 4.4.2 4.4.3 4.4.4 4.4.5 4.4.6 4.4.7 4.4.8 4.4.9 4.5.0 4.5.1 4.5.10 4.5.11 4.5.2 4.5.3 4.5.4 4.5.6 4.5.7 4.5.8 4.5.9
redux-framework / redux-core / class-redux-core.php
redux-framework / redux-core Last commit date
assets 1 year ago core 1 year ago inc 1 year ago languages 1 year ago templates 1 year ago class-redux-core.php 1 year ago framework.php 1 year ago index.php 1 year ago
class-redux-core.php
631 lines
1 <?php
2 /**
3 * Redux Core Class
4 *
5 * @class Redux_Core
6 * @version 4.0.0
7 * @package Redux Framework
8 */
9
10 defined( 'ABSPATH' ) || exit;
11
12 if ( ! class_exists( 'Redux_Core', false ) ) {
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 );
244
245 // phpcs:disable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
246 if ( ! empty( $_SERVER['SERVER_SOFTWARE'] ) ) {
247 self::$server['SERVER_SOFTWARE'] = sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) );
248 }
249 if ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) {
250 self::$server['REMOTE_ADDR'] = sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) );
251 }
252 if ( ! empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
253 self::$server['HTTP_USER_AGENT'] = sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) );
254 }
255 if ( ! empty( $_SERVER['HTTP_HOST'] ) ) {
256 self::$server['HTTP_HOST'] = sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) );
257 }
258 if ( ! empty( $_SERVER['REQUEST_URI'] ) ) {
259 self::$server['REQUEST_URI'] = sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) );
260 }
261
262 // phpcs:enable
263
264 self::$dir = trailingslashit( wp_normalize_path( dirname( realpath( __FILE__ ) ) ) );
265
266 Redux_Functions_Ex::generator();
267
268 if ( defined( 'REDUX_PLUGIN_FILE' ) ) {
269 $plugin_info = Redux_Functions_Ex::is_inside_plugin( REDUX_PLUGIN_FILE );
270 }
271
272 $plugin_info = Redux_Functions_Ex::is_inside_plugin( __FILE__ );
273
274 if ( false !== $plugin_info ) {
275 self::$installed = class_exists( 'Redux_Framework_Plugin' ) ? 'plugin' : 'in_plugin';
276 self::$is_plugin = class_exists( 'Redux_Framework_Plugin' );
277 self::$as_plugin = true;
278 self::$url = trailingslashit( dirname( $plugin_info['url'] ) );
279 } else {
280 $theme_info = Redux_Functions_Ex::is_inside_theme( __FILE__ );
281 if ( false !== $theme_info ) {
282 self::$url = trailingslashit( dirname( $theme_info['url'] ) );
283 self::$in_theme = true;
284 self::$installed = 'in_theme';
285 }
286 }
287
288 // phpcs:ignore WordPress.NamingConventions.ValidHookName
289 self::$url = apply_filters( 'redux/url', self::$url );
290
291 // phpcs:ignore WordPress.NamingConventions.ValidHookName
292 self::$dir = apply_filters( 'redux/dir', self::$dir );
293
294 // phpcs:ignore WordPress.NamingConventions.ValidHookName
295 self::$is_plugin = apply_filters( 'redux/is_plugin', self::$is_plugin );
296
297 if ( ! function_exists( 'current_time' ) ) {
298 require_once ABSPATH . '/wp-includes/functions.php';
299 }
300
301 $upload_dir = wp_upload_dir();
302 self::$upload_dir = $upload_dir['basedir'] . '/redux/';
303 self::$upload_url = str_replace( array( 'https://', 'http://' ), '//', $upload_dir['baseurl'] . '/redux/' );
304
305 // phpcs:ignore WordPress.NamingConventions.ValidHookName
306 self::$upload_dir = apply_filters( 'redux/upload_dir', self::$upload_dir );
307
308 // phpcs:ignore WordPress.NamingConventions.ValidHookName
309 self::$upload_url = apply_filters( 'redux/upload_url', self::$upload_url );
310 }
311
312 /**
313 * Code to execute on a framework __construct.
314 *
315 * @param ReduxFramework $redux Pointer to ReduxFramework object.
316 */
317 public static function core_construct( ReduxFramework $redux ) {
318 self::$third_party_fixes = new Redux_ThirdParty_Fixes( $redux );
319
320 Redux_ThemeCheck::get_instance();
321 }
322
323 /**
324 * Autoregister run.
325 *
326 * @throws Exception Comment.
327 */
328 private function includes() {
329 if ( is_admin() ) {
330 if ( class_exists( 'Redux_Pro' ) && isset( Redux_Pro::$dir ) ) {
331 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>';
332 }
333 }
334
335 require_once __DIR__ . '/inc/classes/class-redux-path.php';
336 require_once __DIR__ . '/inc/classes/class-redux-functions-ex.php';
337 require_once __DIR__ . '/inc/classes/class-redux-helpers.php';
338 require_once __DIR__ . '/inc/classes/class-redux-instances.php';
339
340 Redux_Functions_Ex::register_class_path( 'Redux', __DIR__ . '/inc/classes' );
341 Redux_Functions_Ex::register_class_path( 'Redux', __DIR__ . '/inc/welcome' );
342
343 spl_autoload_register( array( $this, 'register_classes' ) );
344
345 self::$welcome = new Redux_Welcome();
346
347 add_filter( 'debug_information', array( $this, 'add_debug_info' ) );
348 }
349
350 /**
351 * Add debug info for the WP Site Health screen.
352 *
353 * @param array $debug_info Debug data.
354 *
355 * @return array
356 * @throws ReflectionException Exception.
357 */
358 public function add_debug_info( array $debug_info ): array {
359
360 // Get browser data.
361 if ( ! class_exists( 'ReduxBrowser' ) ) {
362 require_once self::$dir . 'inc/lib/browser.php';
363 }
364
365 $browser = new ReduxBrowser();
366
367 $browser_data = array(
368 'Agent' => $browser->getUserAgent(),
369 'Browser' => $browser->getBrowser(),
370 'Version' => $browser->getVersion(),
371 'Platform' => $browser->getPlatform(),
372 );
373
374 // Set Redux dir permission results to Site Health screen.
375 $debug_info['wp-filesystem']['fields'][] = array(
376 'label' => esc_html__( 'The Redux upload directory', 'redux-framework' ),
377 'value' => wp_is_writable( self::$upload_dir ) ? 'Writable' : 'Not writable',
378 );
379
380 // Set Redux plugin results to Site Health screen.
381 $debug_info['redux-framework'] = array(
382 'label' => esc_html__( 'Redux Framework', 'redux-framework' ),
383 'description' => esc_html__( 'Debug information specific to Redux Framework.', 'redux-framework' ),
384 'fields' => array(
385 'version' => array(
386 'label' => esc_html__( 'Version', 'redux-framework' ),
387 'value' => self::$version,
388 ),
389 'installation' => array(
390 'label' => esc_html__( 'Installation', 'redux-framework' ),
391 'value' => self::$installed,
392 ),
393 'data directory' => array(
394 'label' => esc_html__( 'Data directory', 'redux-framework' ),
395 'value' => self::$dir,
396 ),
397 'browser' => array(
398 'label' => esc_html__( 'Browser', 'redux-framework' ),
399 'value' => $browser_data,
400 ),
401 ),
402 );
403
404 $redux = Redux::all_instances();
405
406 $extensions = array();
407
408 if ( ! empty( $redux ) && is_array( $redux ) ) {
409 foreach ( $redux as $inst => $data ) {
410 Redux::init( $inst );
411
412 $inst_name = ucwords( str_replace( array( '_', '-' ), ' ', $inst ) );
413 $args = $data->args;
414
415 $ext = Redux::get_extensions( $inst );
416 if ( ! empty( $ext ) && is_array( $ext ) ) {
417 ksort( $ext );
418
419 foreach ( $ext as $name => $arr ) {
420 $ver = $arr['version'];
421
422 $ex = esc_html( ucwords( str_replace( array( '_', '-' ), ' ', $name ) ) );
423
424 $extensions[ $ex ] = esc_html( $ver );
425 }
426 }
427
428 // Output Redux instances.
429 $debug_info[ 'redux-instance-' . $inst ] = array(
430 // translators: %s = Instance name.
431 'label' => sprintf( esc_html__( 'Redux Instance: %s', 'redux-framework' ), $inst_name ),
432 // translators: %s = Instance name w/ HTML.
433 'description' => sprintf( esc_html__( 'Debug information for the %s Redux instance.', 'redux-framework' ), '<code>' . $inst . '</code>' ),
434 'fields' => array(
435 'opt_name' => array(
436 'label' => esc_html( 'opt_name' ),
437 'value' => $args['opt_name'],
438 ),
439 'global_variable' => array(
440 'label' => esc_html( 'global_variable' ),
441 'value' => $args['global_variable'],
442 ),
443 'dev_mode' => array(
444 'label' => esc_html( 'dev_mode' ),
445 'value' => $args['dev_mode'] ? 'true' : 'false',
446 ),
447 'ajax_save' => array(
448 'label' => esc_html( 'ajax_save' ),
449 'value' => $args['ajax_save'] ? 'true' : 'false',
450 ),
451 'page_slug' => array(
452 'label' => esc_html( 'page_slug' ),
453 'value' => $args['page_slug'],
454 ),
455 'page_permissions' => array(
456 'label' => esc_html( 'page_permissions' ),
457 'value' => $args['page_permissions'],
458 ),
459 'menu_type' => array(
460 'label' => esc_html( 'menu_type' ),
461 'value' => $args['menu_type'],
462 ),
463 'page_parent' => array(
464 'label' => esc_html( 'page_parent' ),
465 'value' => $args['page_parent'],
466 ),
467 'compiler' => array(
468 'label' => esc_html( 'compiler' ),
469 'value' => $args['compiler'] ? 'true' : 'false',
470 ),
471 'output' => array(
472 'label' => esc_html( 'output' ),
473 'value' => $args['output'] ? 'true' : 'false',
474 ),
475 'output_tag' => array(
476 'label' => esc_html( 'output_tag' ),
477 'value' => $args['output_tag'] ? 'true' : 'false',
478 ),
479 'templates_path' => array(
480 'label' => esc_html( 'templates_path' ),
481 'value' => $args['templates_path'],
482 ),
483 'extensions' => array(
484 'label' => esc_html( 'extensions' ),
485 'value' => $extensions,
486 ),
487 ),
488 );
489 }
490 }
491
492 return $debug_info;
493 }
494
495 /**
496 * Register callback for autoload.
497 *
498 * @param string $class_name name of class.
499 */
500 public function register_classes( string $class_name ) {
501 $class_name_test = self::strtolower( $class_name );
502
503 if ( strpos( $class_name_test, 'redux' ) === false ) {
504 return;
505 }
506
507 if ( ! class_exists( 'Redux_Functions_Ex' ) ) {
508 require_once Redux_Path::get_path( '/inc/classes/class-redux-functions-ex.php' );
509 }
510
511 if ( ! class_exists( $class_name ) ) {
512 // Backward compatibility for extensions sucks!
513 if ( 'Redux_Instances' === $class_name ) {
514 require_once Redux_Path::get_path( '/inc/classes/class-redux-instances.php' );
515 require_once Redux_Path::get_path( '/inc/lib/redux-instances.php' );
516
517 return;
518 }
519
520 // Load Redux APIs.
521 if ( 'Redux' === $class_name ) {
522 require_once Redux_Path::get_path( '/inc/classes/class-redux-api.php' );
523
524 return;
525 }
526
527 // Redux extra theme checks.
528 if ( 'Redux_ThemeCheck' === $class_name ) {
529 require_once Redux_Path::get_path( '/inc/themecheck/class-redux-themecheck.php' );
530
531 return;
532 }
533
534 if ( 'Redux_Welcome' === $class_name ) {
535 require_once Redux_Path::get_path( '/inc/welcome/class-redux-welcome.php' );
536
537 return;
538 }
539
540 $mappings = array(
541 'ReduxFrameworkInstances' => 'Redux_Instances',
542 'reduxCorePanel' => 'Redux_Panel',
543 'reduxCoreEnqueue' => 'Redux_Enqueue',
544 'Redux_Abstract_Extension' => 'Redux_Extension_Abstract',
545 );
546 $alias = false;
547 if ( isset( $mappings[ $class_name ] ) ) {
548 $alias = $class_name;
549 $class_name = $mappings[ $class_name ];
550 }
551
552 // Everything else.
553 $file = 'class.' . $class_name_test . '.php';
554
555 $class_path = Redux_Path::get_path( '/inc/classes/' . $file );
556
557 if ( ! file_exists( $class_path ) ) {
558 $class_file_name = str_replace( '_', '-', $class_name );
559 $file = 'class-' . $class_name_test . '.php';
560 $class_path = Redux_Path::get_path( '/inc/classes/' . $file );
561 }
562
563 if ( file_exists( $class_path ) && ! class_exists( $class_name ) ) {
564 require_once $class_path;
565 }
566 if ( class_exists( $class_name ) && ! empty( $alias ) && ! class_exists( $alias ) ) {
567 class_alias( $class_name, $alias );
568 }
569 }
570
571 // phpcs:ignore WordPress.NamingConventions.ValidHookName
572 do_action( 'redux/core/includes', $this );
573 }
574
575 /**
576 * Hooks to run on instance creation.
577 */
578 private function hooks() {
579 // phpcs:ignore WordPress.NamingConventions.ValidHookName
580 do_action( 'redux/core/hooks', $this );
581 }
582
583 /**
584 * Action to run on WordPress heartbeat.
585 *
586 * @return bool
587 */
588 public static function is_heartbeat(): bool {
589 // Disregard WP AJAX 'heartbeat' call. Why waste resources?
590 if ( isset( $_POST ) && isset( $_POST['_nonce'] ) && wp_verify_nonce( sanitize_key( wp_unslash( $_POST['_nonce'] ) ), 'heartbeat-nonce' ) ) {
591
592 if ( isset( $_POST['action'] ) && 'heartbeat' === sanitize_text_field( wp_unslash( $_POST['action'] ) ) ) {
593
594 // Hook, for purists.
595 if ( has_action( 'redux/ajax/heartbeat' ) ) {
596 // phpcs:ignore WordPress.NamingConventions.ValidHookName
597 do_action( 'redux/ajax/heartbeat' );
598 }
599
600 return true;
601 }
602
603 return false;
604 }
605
606 // Buh bye!
607 return false;
608 }
609
610 /**
611 * Helper method to check for mb_strtolower or to use the standard strtolower.
612 *
613 * @param string|null $str String to make lowercase.
614 *
615 * @return string|null
616 */
617 public static function strtolower( ?string $str ): string {
618 if ( function_exists( 'mb_strtolower' ) && function_exists( 'mb_detect_encoding' ) ) {
619 return mb_strtolower( $str, mb_detect_encoding( $str ) );
620 } else {
621 return strtolower( $str );
622 }
623 }
624 }
625
626 /*
627 * Backwards comparability alias
628 */
629 class_alias( 'Redux_Core', 'redux-core' );
630 }
631