re WordPress.PHP.NoSilencedErrors.Discouraged wp_safe_redirect( $url, $status_code ); exit(); } /** * Fallback for wp_sfe_redirect(). * * @static * * @param string $url URL. * @return string */ public static function wp_safe_redirect_fallback( $url ) { return home_url( '?w3tc_repeat=invalid' ); } /** * Detects post ID. * * @static * * @return int */ public static function detect_post_id() { global $posts, $comment_post_ID, $post_ID; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase $p_val = Util_Request::get_integer( 'p' ); if ( $post_ID ) { return $post_ID; } elseif ( $comment_post_ID ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase return $comment_post_ID; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase } elseif ( ( is_single() || is_page() ) && is_array( $posts ) && isset( $posts[0]->ID ) ) { return $posts[0]->ID; } elseif ( isset( $posts->ID ) ) { return $posts->ID; } elseif ( ! empty( $p_val ) ) { return $p_val; } return 0; } /** * Get W3TC instance id. * * @static * * @return int */ public static function instance_id() { if ( defined( 'W3TC_INSTANCE_ID' ) ) { return W3TC_INSTANCE_ID; } static $instance_id; if ( ! isset( $instance_id ) ) { $config = Dispatcher::config(); $instance_id = $config->get_integer( 'common.instance_id', 0 ); } return $instance_id; } /** * Get W3TC edition. * * @static * * @param Config $config Config. * @return string */ public static function w3tc_edition( $config = null ) { if ( self::is_w3tc_pro( $config ) && self::is_w3tc_pro_dev() ) { return 'pro development'; } if ( self::is_w3tc_pro( $config ) ) { return 'pro'; } return 'community'; } /** * Is W3TC Pro. * * @static * * @param Config $config Config. * @return bool */ public static function is_w3tc_pro( $config = null ) { if ( defined( 'W3TC_PRO' ) && W3TC_PRO ) { return true; } if ( defined( 'W3TC_ENTERPRISE' ) && W3TC_ENTERPRISE ) { return true; } if ( is_object( $config ) ) { $plugin_type = $config->get_string( 'plugin.type' ); if ( 'pro' === $plugin_type || 'pro_dev' === $plugin_type ) { return true; } } return false; } /** * Enable Pro Dev mode support. * * @static * * @return bool */ public static function is_w3tc_pro_dev() { return defined( 'W3TC_PRO_DEV_MODE' ) && W3TC_PRO_DEV_MODE; } /** * Quotes regular expression string. * * @static * * @param string $string String. * @param string $delimiter Delimeter. * @return string */ public static function preg_quote( $string, $delimiter = '~' ) { $string = preg_quote( $string, $delimiter ); $string = strtr( $string, array( ' ' => '\ ' ) ); return $string; } /** * Returns true if zlib output compression is enabled otherwise false. * * @static * * @return bool */ public static function is_zlib_enabled() { return self::to_boolean( ini_get( 'zlib.output_compression' ) ); } /** * Recursive strips slahes from the var. * * @static * * @param mixed $var Value. * @return mixed */ public static function stripslashes( $var ) { if ( is_string( $var ) ) { return stripslashes( $var ); } elseif ( is_array( $var ) ) { $var = array_map( array( '\W3TC\Util_Environment', 'stripslashes' ), $var ); } return $var; } /** * Checks if post should be flushed or not. Returns true if it should not be flushed. * * @static * * @param object $post Post object. * @param string $module Which cache module to check against (pgcache, varnish, dbcache or objectcache). * @param Config $config Config. * @return bool */ public static function is_flushable_post( $post, $module, $config ) { if ( is_numeric( $post ) ) { $post = get_post( $post ); } $post_status = array( 'publish' ); /** * Dont flush when we have post "attachment" * its child of the post and is flushed always when post is published, while not changed in fact. */ $post_type = array( 'revision', 'attachment' ); switch ( $module ) { case 'pgcache': case 'varnish': case 'posts': // Means html content of post pages. if ( ! $config->get_boolean( 'pgcache.reject.logged' ) ) { $post_status[] = 'private'; } break; case 'dbcache': if ( ! $config->get_boolean( 'dbcache.reject.logged' ) ) { $post_status[] = 'private'; } break; } $flushable = is_object( $post ) && ! in_array( $post->post_type, $post_type, true ) && in_array( $post->post_status, $post_status, true ); return apply_filters( 'w3tc_flushable_post', $flushable, $post, $module ); } /** * Checks if post belongs to a custom post type. * * @since 2.1.7 * @static * * @param object $post Post object. * @return bool */ public static function is_custom_post_type( $post ) { $post_type = get_post_type_object( $post->post_type ); // post type not found belongs to default post type(s). if ( empty( $post_type ) ) { return false; } // check if custom. if ( false === $post_type->_builtin ) { return true; } return false; } /** * Converts value to boolean. * * @static * * @param mixed $value Value. * @return bool */ public static function to_boolean( $value ) { if ( is_string( $value ) ) { switch ( strtolower( $value ) ) { case '+': case '1': case 'y': case 'on': case 'yes': case 'true': case 'enabled': return true; case '-': case '0': case 'n': case 'no': case 'off': case 'false': case 'disabled': return false; } } return (boolean) $value; } /** * Returns the apache, nginx version. * * @static * * @return string */ public static function get_server_version() { $sig = explode( '/', isset( $_SERVER['SERVER_SOFTWARE'] ) ? htmlspecialchars( stripslashes( $_SERVER['SERVER_SOFTWARE'] ) ) : '' // phpcs:ignore ); $temp = isset( $sig[1] ) ? explode( ' ', $sig[1] ) : array( '0' ); $version = $temp[0]; return $version; } /** * Checks if current request is REST REQUEST. * * @static */ public static function is_rest_request( $url ) { if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) return true; // in case when called before constant is set // wp filters are not available in that case return preg_match( '~' . W3TC_WP_JSON_URI . '~', $url ); } /** * Reset microcache. * * @static */ public static function reset_microcache() { global $w3_current_blog_id; $w3_current_blog_id = null; self::$is_using_master_config = null; } /** * Removes blank lines, trim values, removes duplicates, and sorts array. * * @since 2.4.3 * * @param array $values Array of values. * * @return array */ public static function clean_array( $values ) { if ( ! empty( $values ) && is_array( $values ) ) { $values = array_unique( array_filter( array_map( 'trim', $values ), 'strlen' ) ); sort( $values ); } return $values; } /** * Parses textarea setting value from string to array. * * @since 2.4.3 * * @param string $value Value. * * @return array */ public static function textarea_to_array( $value ) { $values_array = array(); if ( ! empty( $value ) ) { $values_array = self::clean_array( preg_split( '/\R/', $value, 0, PREG_SPLIT_NO_EMPTY ) ); } return $values_array; } /** * Is there a partial array intersections match? * * Returns true if any entries between the tewo arrays match string endings or in whole. * * @since 2.7.4 * @static * * @param array $array1 Array 1. * @param array $array2 Array 2. * @return bool */ public static function array_intersect_partial( array $array1, array $array2 ): bool { foreach ( $array1 as $url1 ) { foreach ( $array2 as $url2 ) { /** * Parse array1 URLs to handle both full URLs and relative paths. * If homepage then 'path' will be null, set to '/'. */ $parsed_url1 = \wp_parse_url( \trim( $url1, '/' ) ); $parsed_url1['path'] = $parsed_url1['path'] ?? '/'; /** * Parse array2 URLs to handle both full URLs and relative paths. * If value is '/' for homepage then don't trim, otherwise tirm. */ $parsed_url2 = \wp_parse_url( '/' === $url2 ? '/' : \trim( $url2, '/' ) ); $is_host_set = isset( $parsed_url1['host'], $parsed_url2['host'] ); if ( $url1 === $url2 ) { // Direct comparison for full URLs that are identical. return true; } elseif ( isset( $parsed_url1['path'], $parsed_url2['path'] ) && ( \substr( $parsed_url1['path'], -\strlen( $parsed_url2['path'] ) ) === $parsed_url2['path'] || \substr( $parsed_url2['path'], -\strlen( $parsed_url1['path'] ) ) === $parsed_url1['path'] ) && ( ! $is_host_set || ( $is_host_set && $parsed_url1['host'] === $parsed_url2['host'] ) ) ) { /** * Check if both parsed URLs have 'path' and 'host' component and if they match. * If either 'host' is not set but 'path' matches, consider it a match. */ return true; } } } return false; } /** * Generates an appropriate timestamp for WP cron using a selected time during the day in the form of an integer. * Adjusts for discrepacy in timezones between WP and system and adds a day if the result is in the past. * * @since 2.8.0 * * @static * * @param int $cron_time Cron schedule time. * * @return int */ public static function get_cron_schedule_time(int $cron_time = 0): int { // Get the current time in WordPress timezone. $current_time_wp = new \DateTime( 'now', wp_timezone() ); // Convert the selected cron time into hours and minutes. $hour = floor( $cron_time / 60 ); $minute = $cron_time % 60; // Create a DateTime for today at the specified hour and minute in the user's timezone. $scheduled_time_user = new \DateTime( "today", wp_timezone() ); $scheduled_time_user->setTime( $hour, $minute ); // Convert the user's scheduled time to UTC for WordPress. $scheduled_time_utc = clone $scheduled_time_user; $scheduled_time_utc->setTimezone( new \DateTimeZone('UTC') ); // If the selected time has already passed today in UTC, schedule for tomorrow. if ( $scheduled_time_utc <= $current_time_wp ) { $scheduled_time_utc->modify( '+1 day' ); } return $scheduled_time_utc->getTimestamp(); } /** * Tests the WP Cron spawning system and reports back its status. * * This command tests the spawning system by performing the following steps: * * * Checks to see if the `DISABLE_WP_CRON` constant is set; errors if true * because WP-Cron is disabled. * * Checks to see if the `ALTERNATE_WP_CRON` constant is set; warns if true. * * Attempts to spawn WP-Cron over HTTP; warns if non 200 response code is * returned. * * @since 2.8.0 * @link https://github.com/wp-cli/cron-command/blob/v2.3.1/src/Cron_Command.php#L14-L55 * * @return bool */ public static function is_wpcron_working(): bool { if ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) { $errormsg = 'The DISABLE_WP_CRON constant is set to true. WP-Cron spawning is disabled.'; return false; } if ( defined( 'ALTERNATE_WP_CRON' ) && ALTERNATE_WP_CRON ) { $errormsg = 'The ALTERNATE_WP_CRON constant is set to true. WP-Cron spawning is not asynchronous.'; return false; } $spawn = self::get_cron_spawn(); if ( is_wp_error( $spawn ) ) { $errormsg = sprintf( 'WP-Cron spawn failed with error: %s', $spawn->get_error_message() ); return false; } $code = wp_remote_retrieve_response_code( $spawn ); $message = wp_remote_retrieve_response_message( $spawn ); if ( 200 === $code ) { // WP-Cron spawning is working as expected. return true; } else { $errormsg = sprintf( 'WP-Cron spawn returned HTTP status code: %1$s %2$s', $code, $message ); return false; } } /** * Spawns a request to `wp-cron.php` and return the response. * * This function is designed to mimic the functionality in `spawn_cron()` * with the addition of returning the result of the `wp_remote_post()` * request. * * @since 2.8.0 * @link https://github.com/wp-cli/cron-command/blob/v2.3.1/src/Cron_Command.php#L57-L91 * * @global $wp_version WordPress version string. * * @return WP_Error|array The response or WP_Error on failure. */ protected static function get_cron_spawn() { global $wp_version; $sslverify = version_compare( $wp_version, 4.0, '<' ); $doing_wp_cron = sprintf( '%.22F', microtime( true ) ); $cron_request_array = array( 'url' => site_url( 'wp-cron.php?doing_wp_cron=' . $doing_wp_cron ), 'key' => $doing_wp_cron, 'args' => array( 'timeout' => 3, 'blocking' => true, // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Calling native WordPress hook. 'sslverify' => apply_filters( 'https_local_ssl_verify', $sslverify ), ), ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Calling native WordPress hook. $cron_request = apply_filters( 'cron_request', $cron_request_array ); // Enforce a blocking request in case something that's hooked onto the 'cron_request' filter sets it to false. $cron_request['args']['blocking'] = true; $result = wp_remote_post( $cron_request['url'], $cron_request['args'] ); return $result; } }