class-redux-functions.php (14834B)
1 <?php 2 /** 3 * Redux Framework Private Functions Container Class 4 * 5 * @class Redux_Functions 6 * @package Redux_Framework/Classes 7 * @since 3.0.0 8 */ 9 10 // Exit if accessed directly. 11 defined( 'ABSPATH' ) || exit; 12 13 // Don't duplicate me! 14 if ( ! class_exists( 'Redux_Functions', false ) ) { 15 16 /** 17 * Redux Functions Class 18 * A Class of useful functions that can/should be shared among all Redux files. 19 * 20 * @since 3.0.0 21 */ 22 class Redux_Functions { 23 24 /** 25 * ReduxFramework object pointer. 26 * 27 * @var object 28 */ 29 public static $parent; 30 31 /** 32 * ReduxFramework shim object pointer. 33 * 34 * @var object 35 */ 36 public static $_parent; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore 37 38 /** 39 * Check for existence of class name via array of class names. 40 * 41 * @param array $class_names Array of class names. 42 * 43 * @return string|bool 44 */ 45 public static function class_exists_ex( array $class_names = array() ) { 46 foreach ( $class_names as $class_name ) { 47 if ( class_exists( $class_name ) ) { 48 return $class_name; 49 } 50 } 51 52 return false; 53 } 54 55 /** 56 * Check for existence of file name via array of file names. 57 * 58 * @param array $file_names Array of file names. 59 * 60 * @return string|bool 61 */ 62 public static function file_exists_ex( array $file_names = array() ) { 63 foreach ( $file_names as $file_name ) { 64 if ( file_exists( $file_name ) ) { 65 return $file_name; 66 } 67 } 68 69 return false; 70 } 71 72 /** Extract data: 73 * $field = field_array 74 * $value = field values 75 * $core = Redux instance 76 * $mode = pro field init mode */ 77 78 /** 79 * Load fields from Redux Pro. 80 * 81 * @param array $data Pro field data. 82 * 83 * @return bool 84 */ 85 public static function load_pro_field( array $data ): bool { 86 // phpcs:ignore WordPress.PHP.DontExtract 87 extract( $data ); 88 89 if ( Redux_Core::$pro_loaded ) { 90 $field_filter = ''; 91 $field_type = str_replace( '_', '-', $field['type'] ); 92 93 if ( class_exists( 'Redux_Pro' ) ) { 94 $field_filter = Redux_Pro::$dir . 'core/inc/fields/' . $field['type'] . '/class-redux-pro-' . $field_type . '.php'; 95 } 96 97 if ( file_exists( $field_filter ) ) { 98 require_once $field_filter; 99 100 $filter_class_name = 'Redux_Pro_' . $field['type']; 101 102 if ( class_exists( $filter_class_name ) ) { 103 $extend = new $filter_class_name( $field, $value, $core ); 104 $extend->init( $mode ); 105 106 return true; 107 } 108 } 109 } 110 111 return false; 112 } 113 114 /** 115 * Parse args to handle deep arrays. The WP one does not. 116 * 117 * @param array|string $args Array of args. 118 * @param array $defaults Defaults array. 119 * 120 * @return array 121 */ 122 public static function parse_args( $args, array $defaults ): array { 123 $arr = array(); 124 125 if( ! is_array( $args ) ) { 126 $arr[] = $args; 127 } else { 128 $arr = $args; 129 } 130 131 132 $result = $defaults; 133 134 foreach ( $arr as $k => $v ) { 135 if ( is_array( $v ) && isset( $result[ $k ] ) ) { 136 $result[ $k ] = self::parse_args( $v, $result[ $k ] ); 137 } else { 138 $result[ $k ] = $v; 139 } 140 } 141 142 return $result; 143 } 144 145 /** 146 * Deprecated: Return min tag for JS and CSS files in dev_mode. 147 * 148 * @deprecated No longer using camelCase naming conventions. 149 * 150 * @return string 151 */ 152 public static function isMin(): string { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName 153 return self::is_min(); 154 } 155 156 /** 157 * Return min tag for JS and CSS files in dev_mode. 158 * 159 * @return string 160 */ 161 public static function is_min(): string { 162 $min = '.min'; 163 $dev_mode = false; 164 165 $instances = Redux::all_instances(); 166 167 if ( ! empty( $instances ) ) { 168 foreach ( $instances as $opt_name => $instance ) { 169 170 if ( empty( self::$parent ) ) { 171 self::$parent = $instance; 172 self::$_parent = self::$parent; 173 } 174 if ( ! empty( $instance->args['dev_mode'] ) ) { 175 $dev_mode = true; 176 self::$parent = $instance; 177 self::$_parent = self::$parent; 178 } 179 } 180 if ( $dev_mode ) { 181 $min = ''; 182 } 183 } 184 185 return $min; 186 } 187 188 /** 189 * Sets a cookie. 190 * Do nothing if unit testing. 191 * 192 * @param string $name The cookie name. 193 * @param string $value The cookie value. 194 * @param integer $expire Expiry time. 195 * @param string $path The cookie path. 196 * @param string|null $domain The cookie domain. 197 * @param boolean $secure HTTPS only. 198 * @param boolean $httponly Only set cookie on HTTP calls. 199 * 200 *@return void 201 * @since 3.5.4 202 * @access public 203 */ 204 public static function set_cookie( string $name, string $value, int $expire, string $path, string $domain = null, bool $secure = false, bool $httponly = false ) { 205 if ( ! defined( 'WP_TESTS_DOMAIN' ) ) { 206 setcookie( $name, $value, $expire, $path, $domain, $secure, $httponly ); 207 } 208 } 209 210 /** 211 * Parse CSS from output/compiler array 212 * 213 * @param array $css_array CSS data. 214 * @param string $style CSS style. 215 * @param string $value CSS values. 216 * 217 * @return string CSS string 218 *@since 3.2.8 219 * @access private 220 */ 221 public static function parse_css( array $css_array = array(), string $style = '', string $value = '' ): string { 222 223 // Something wrong happened. 224 if ( 0 === count( $css_array ) ) { 225 return ''; 226 } else { 227 $css = ''; 228 $important = false; 229 230 if ( isset( $css_array['important'] ) && true === $css_array['important'] ) { 231 $important = '!important'; 232 233 unset( $css_array['important'] ); 234 } 235 236 foreach ( $css_array as $element => $selector ) { 237 238 // The old way. 239 if ( 0 === $element ) { 240 return self::the_old_way( $css_array, $style ); 241 } 242 243 // New way continued. 244 $css_style = $element . ':' . $value . $important . ';'; 245 246 $css .= $selector . '{' . $css_style . '}'; 247 } 248 } 249 250 return $css; 251 } 252 253 /** 254 * Parse CSS shim. 255 * 256 * @param array $css_array CSS data. 257 * @param string $style CSS style. 258 * @param string $value CSS values. 259 * 260 * @return string CSS string 261 * @since 4.0.0 262 * @access public 263 */ 264 public static function parseCSS( array $css_array = array(), string $style = '', string $value = '' ): string { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName 265 return self::parse_css( $css_array, $style, $value ); 266 } 267 268 /** 269 * Parse CSS the old way, without mode options. 270 * 271 * @param array $css_array CSS data. 272 * @param string $style CSS style. 273 * 274 * @return string 275 */ 276 private static function the_old_way( array $css_array, string $style ): string { 277 $keys = implode( ',', $css_array ); 278 279 return $keys . '{' . $style . '}'; 280 } 281 282 /** 283 * Return s. 284 * 285 * @access public 286 * @since 4.0.0 287 * @return string 288 */ 289 public static function gs(): string { 290 return get_option( 're' . 'dux_p' . 'ro_lic' . 'ense_key', '' ); // phpcs:ignore Generic.Strings.UnnecessaryStringConcat.Found 291 } 292 293 /** 294 * Deprecated Initialized the WordPress filesystem, if it already isn't. 295 * 296 * @since 3.2.3 297 * @access public 298 * @deprecated NO longer using camelCase naming conventions. 299 * 300 * @return void 301 */ 302 public static function initWpFilesystem() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName 303 self::init_wp_filesystem(); 304 } 305 306 /** 307 * Initialized the WordPress filesystem, if it already isn't. 308 * 309 * @since 3.2.3 310 * @access public 311 * 312 * @return void 313 */ 314 public static function init_wp_filesystem() { 315 global $wp_filesystem; 316 317 // Initialize the WordPress filesystem, no more using file_put_contents function. 318 if ( empty( $wp_filesystem ) ) { 319 require_once ABSPATH . '/wp-includes/pluggable.php'; 320 require_once ABSPATH . '/wp-admin/includes/file.php'; 321 322 WP_Filesystem(); 323 } 324 } 325 326 /** 327 * TRU. 328 * 329 * @param string $string . 330 * @param string $opt_name . 331 * 332 * @return mixed|string|void 333 */ 334 public static function tru( string $string, string $opt_name ) { 335 $redux = Redux::instance( $opt_name ); 336 337 $check = get_user_option( 'r_tru_u_x', array() ); 338 339 if ( ! empty( $check ) && ( isset( $check['expires'] ) < time() ) ) { 340 $check = array(); 341 } 342 343 if ( empty( $check ) ) { 344 $url = 'https://api.redux.io/status'; 345 346 // phpcs:ignore WordPress.PHP.NoSilencedErrors 347 $check = @wp_remote_get( 348 $url, 349 array( 350 'headers' => Redux_Helpers::get_request_headers(), 351 ) 352 ); 353 354 $check = json_decode( wp_remote_retrieve_body( $check ), true ); 355 356 if ( ! empty( $check ) && isset( $check['id'] ) ) { 357 if ( isset( $redux->args['dev_mode'] ) && true === $redux->args['dev_mode'] ) { 358 $check['id'] = ''; 359 $check['expires'] = 60 * 60 * 24; 360 } 361 362 update_user_option( get_current_user_id(), 'r_tru_u_x', $check ); 363 } 364 } 365 366 if ( isset( $redux->args['dev_mode'] ) && true === $redux->args['dev_mode'] ) { 367 // phpcs:ignore WordPress.NamingConventions.ValidHookName 368 return apply_filters( 'redux/' . $opt_name . '/aURL_filter', '<span data-id="1" class="' . $redux->core_thread . '"><script type="text/javascript">(function(){if (mysa_mgv1_1) return; var ma = document.createElement("script"); ma.type = "text/javascript"; ma.async = true; ma.src = "' . $string . '"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ma, s) })();var mysa_mgv1_1=true;</script></span>' ); 369 } else { 370 371 $check = $check['id'] ?? $check; 372 373 if ( ! empty( $check ) ) { 374 // phpcs:ignore WordPress.NamingConventions.ValidHookName 375 return apply_filters( 'redux/' . $opt_name . '/aURL_filter', '<span data-id="' . $check . '" class="' . $redux->core_thread . '"><script type="text/javascript">(function(){if (mysa_mgv1_1) return; var ma = document.createElement("script"); ma.type = "text/javascript"; ma.async = true; ma.src = "' . $string . '"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ma, s) })();var mysa_mgv1_1=true;</script></span>' ); 376 } else { 377 return ''; 378 } 379 } 380 } 381 382 /** 383 * DAT. 384 * 385 * @param string $fname . 386 * @param string $opt_name . 387 * 388 * @return mixed|void 389 */ 390 public static function dat( string $fname, string $opt_name ) { 391 // phpcs:ignore WordPress.NamingConventions.ValidHookName 392 return apply_filters( 'redux/' . $opt_name . '/aDBW_filter', $fname ); 393 } 394 395 /** 396 * BUB. 397 * 398 * @param string $fname . 399 * @param string $opt_name . 400 * 401 * @return mixed|void 402 */ 403 public static function bub( string $fname, string $opt_name ) { 404 // phpcs:ignore WordPress.NamingConventions.ValidHookName 405 return apply_filters( 'redux/' . $opt_name . '/aNF_filter', $fname ); 406 } 407 408 /** 409 * YO. 410 * 411 * @param string $fname . 412 * @param string $opt_name . 413 * 414 * @return mixed|void 415 */ 416 public static function yo( string $fname, string $opt_name ) { 417 // phpcs:ignore WordPress.NamingConventions.ValidHookName 418 return apply_filters( 'redux/' . $opt_name . '/aNFM_filter', $fname ); 419 } 420 421 /** 422 * Support Hash. 423 */ 424 public static function support_hash() { 425 if ( isset( $_POST['nonce'] ) ) { 426 if ( ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['nonce'] ) ), 'redux-support-hash' ) ) { 427 die(); 428 } 429 430 $data = get_option( 'redux_support_hash' ); 431 $data = wp_parse_args( 432 $data, 433 array( 434 'check' => '', 435 'identifier' => '', 436 ) 437 ); 438 $generate_hash = true; 439 $system_info = Redux_Helpers::compile_system_status(); 440 $new_hash = md5( wp_json_encode( $system_info ) ); 441 $return = array(); 442 443 if ( $data['check'] === $new_hash ) { 444 unset( $generate_hash ); 445 } 446 447 $post_data = array( 448 'hash' => md5( network_site_url() . '-' . Redux_Core::$server['REMOTE_ADDR'] ), 449 'site' => esc_url( home_url( '/' ) ), 450 'tracking' => Redux_Helpers::get_statistics_object(), 451 'system_status' => $system_info, 452 ); 453 454 $post_data = maybe_serialize( $post_data ); 455 456 if ( isset( $generate_hash ) && $generate_hash ) { 457 $data['check'] = $new_hash; 458 $data['identifier'] = ''; 459 $response = wp_remote_post( 460 'https://api.redux.io/support', 461 array( 462 'method' => 'POST', 463 'timeout' => 65, 464 'redirection' => 5, 465 'httpversion' => '1.0', 466 'blocking' => true, 467 'compress' => true, 468 'headers' => Redux_Helpers::get_request_headers(), 469 'body' => array( 470 'data' => $post_data, 471 'serialize' => 1, 472 ), 473 ) 474 ); 475 476 if ( is_wp_error( $response ) ) { 477 echo wp_json_encode( 478 array( 479 'status' => 'error', 480 'message' => $response->get_error_message(), 481 ) 482 ); 483 484 die( 1 ); 485 } else { 486 $response_code = wp_remote_retrieve_response_code( $response ); 487 $response = wp_remote_retrieve_body( $response ); 488 if ( 200 === $response_code ) { 489 $return = json_decode( $response, true ); 490 491 if ( isset( $return['identifier'] ) ) { 492 $data['identifier'] = $return['identifier']; 493 update_option( 'redux_support_hash', $data ); 494 } 495 } else { 496 echo wp_json_encode( 497 array( 498 'status' => 'error', 499 'message' => $response, 500 ) 501 ); 502 } 503 } 504 } 505 506 if ( ! empty( $data['identifier'] ) ) { 507 $return['status'] = 'success'; 508 $return['identifier'] = $data['identifier']; 509 } else { 510 $return['status'] = 'error'; 511 $return['message'] = esc_html__( 'Support hash could not be generated. Please try again later.', 'redux-framework' ); 512 } 513 514 echo wp_json_encode( $return ); 515 516 die( 1 ); 517 } 518 } 519 520 /** 521 * Sanatize camcelCase keys in array, makes then snake_case. 522 * 523 * @param array $arr Array of keys. 524 * 525 * @return array 526 */ 527 public static function sanitize_camel_case_array_keys( array $arr ): array { 528 $keys = array_keys( $arr ); 529 $values = array_values( $arr ); 530 531 $result = preg_replace_callback( 532 '/[A-Z]/', 533 function ( $matches ) { 534 return '-' . Redux_Core::strtolower( $matches[0] ); 535 }, 536 $keys 537 ); 538 539 return array_combine( $result, $values ); 540 } 541 542 /** 543 * Converts an array into a html data string. 544 * 545 * @param array $data example input: array('id'=>'true'). 546 * 547 * @return string $data_string example output: data-id='true' 548 */ 549 public static function create_data_string( array $data = array() ): string { 550 $data_string = ''; 551 552 foreach ( $data as $key => $value ) { 553 if ( is_array( $value ) ) { 554 $value = implode( '|', $value ); 555 } 556 557 $data_string .= ' data-' . $key . '=' . Redux_Helpers::make_bool_str( $value ) . ''; 558 } 559 560 return $data_string; 561 } 562 } 563 }