is_page ) { $page_type = is_front_page() ? 'front' : 'page'; } elseif ( $wp_query->is_home ) { $page_type = 'home'; } elseif ( $wp_query->is_single ) { // $page_type = $wp_query->is_attachment ? 'attachment' : 'single'; $page_type = get_post_type(); } elseif ( $wp_query->is_category ) { $page_type = 'category'; } elseif ( $wp_query->is_tag ) { $page_type = 'tag'; } elseif ( $wp_query->is_tax ) { $page_type = 'tax'; // $page_type = get_queried_object()->taxonomy; } elseif ( $wp_query->is_archive ) { if ( $wp_query->is_day ) { $page_type = 'day'; } elseif ( $wp_query->is_month ) { $page_type = 'month'; } elseif ( $wp_query->is_year ) { $page_type = 'year'; } elseif ( $wp_query->is_author ) { $page_type = 'author'; } else { $page_type = 'archive'; } } elseif ( $wp_query->is_search ) { $page_type = 'search'; } elseif ( $wp_query->is_404 ) { $page_type = '404'; } return $page_type; // if ( is_404() ) { // $page_type = '404'; // } // elseif ( is_singular() ) { // $page_type = get_post_type(); // } // elseif ( is_home() && get_option( 'show_on_front' ) == 'page' ) { // $page_type = 'home'; // } // elseif ( is_front_page() ) { // $page_type = 'front'; // } // elseif ( is_tax() ) { // $page_type = get_queried_object()->taxonomy; // } // elseif ( is_category() ) { // $page_type = 'category'; // } // elseif ( is_tag() ) { // $page_type = 'tag'; // } // return $page_type; } /** * Get ping speed * * @since 2.9 */ public static function ping( $domain ) { if ( strpos( $domain, ':' ) ) { $domain = parse_url( $domain, PHP_URL_HOST ); } $starttime = microtime( true ); $file = fsockopen( $domain, 443, $errno, $errstr, 10 ); $stoptime = microtime( true ); $status = 0; if ( ! $file ) $status = 99999;// Site is down else { fclose( $file ); $status = ( $stoptime - $starttime ) * 1000; $status = floor( $status ); } Debug2::debug( "[Util] ping [Domain] $domain \t[Speed] $status" ); return $status; } /** * Set seconds/timestamp to readable format * * @since 1.6.5 * @access public */ public static function readable_time( $seconds_or_timestamp, $timeout = 3600, $forword = false ) { if ( strlen( $seconds_or_timestamp ) == 10 ) { $seconds = time() - $seconds_or_timestamp; if ( $seconds > $timeout ) { return date( 'm/d/Y H:i:s', $seconds_or_timestamp + LITESPEED_TIME_OFFSET ); } } else { $seconds = $seconds_or_timestamp; } $res = ''; if ( $seconds > 86400 ) { $num = floor( $seconds / 86400 ); $res .= $num . 'd'; $seconds %= 86400; } if ( $seconds > 3600 ) { if ( $res ) { $res .= ', '; } $num = floor( $seconds / 3600 ); $res .= $num . 'h'; $seconds %= 3600; } if ( $seconds > 60 ) { if ( $res ) { $res .= ', '; } $num = floor( $seconds / 60 ); $res .= $num . 'm'; $seconds %= 60; } if ( $seconds > 0 ) { if ( $res ) { $res .= ' '; } $res .= $seconds . 's'; } if ( ! $res ) { return $forword ? __( 'right now', 'litespeed-cache' ) : __( 'just now', 'litespeed-cache' ); } $res = $forword ? $res : sprintf( __( ' %s ago', 'litespeed-cache' ), $res ); return $res; } /** * Convert array to string * * @since 1.6 * @access public */ public static function arr2str( $arr ) { if ( ! is_array( $arr ) ) { return $arr; } return base64_encode( json_encode( $arr ) ); } /** * Get human readable size * * @since 1.6 * @access public */ public static function real_size( $filesize, $is_1000 = false ) { $unit = $is_1000 ? 1000 : 1024; if ( $filesize >= pow( $unit, 3 ) ) { $filesize = round( $filesize / pow( $unit, 3 ) * 100 ) / 100 . 'G'; } elseif ( $filesize >= pow( $unit, 2 ) ) { $filesize = round( $filesize / pow( $unit, 2 ) * 100 ) / 100 . 'M'; } elseif ( $filesize >= $unit ) { $filesize = round( $filesize / $unit * 100 ) / 100 . 'K'; } else { $filesize = $filesize . 'B'; } return $filesize; } /** * Parse attributes from string * * @since 1.2.2 * @since 1.4 Moved from optimize to utility * @access private * @param string $str * @return array All the attributes */ public static function parse_attr( $str ) { $attrs = array(); preg_match_all( '#([\w-]+)=(\'|")([^\2]*)\2#isU', $str, $matches, PREG_SET_ORDER ); foreach ( $matches as $match ) { $attrs[ $match[ 1 ] ] = trim( $match[ 3 ] ); } return $attrs; } /** * Check if an array has a string * * Support $ exact match * * @since 1.3 * @access private * @param string $needle The string to search with * @param array $haystack * @return bool|string False if not found, otherwise return the matched string in haystack. */ public static function str_hit_array( $needle, $haystack, $has_ttl = false ) { if ( ! $haystack ) { return false; } /** * Safety check to avoid PHP warning * @see https://github.com/litespeedtech/lscache_wp/pull/131/commits/45fc03af308c7d6b5583d1664fad68f75fb6d017 */ if ( ! is_array( $haystack ) ) { Debug2::debug( "[Util] ❌ bad param in str_hit_array()!" ); return false; } $hit = false; $this_ttl = 0; foreach( $haystack as $item ) { if ( ! $item ) { continue; } if ( $has_ttl ) { $this_ttl = 0; $item = explode( ' ', $item ); if ( ! empty( $item[ 1 ] ) ) { $this_ttl = $item[ 1 ]; } $item = $item[ 0 ]; } if ( substr( $item, -1 ) === '$' ) { // do exact match if ( substr( $item, 0, -1 ) === $needle ) { $hit = $item; break; } } elseif ( substr( $item, 0, 1 ) === '^' ) { // match beginning if ( substr( $item, 1 ) === substr( $needle, 0, strlen( $item ) - 1 ) ) { $hit = $item; break; } } else { if ( strpos( $needle, $item ) !== false ) { $hit = $item; break; } } } if ( $hit ) { if ( $has_ttl ) { return array( $hit, $this_ttl ); } return $hit; } return false; } /** * Improve compatibility to PHP old versions * * @since 1.2.2 * */ public static function compatibility() { require_once LSCWP_DIR . 'lib/php-compatibility.func.php'; } /** * Convert URI to URL * * @since 1.3 * @access public * @param string $uri `xx/xx.html` or `/subfolder/xx/xx.html` * @return string http://www.example.com/subfolder/xx/xx.html */ public static function uri2url( $uri ) { if ( substr( $uri, 0, 1 ) === '/' ) { self::domain_const(); $url = LSCWP_DOMAIN . $uri; } else { $url = home_url( '/' ) . $uri; } return $url; } /** * Convert URL to URI * * @since 1.2.2 * @since 1.6.2.1 Added 2nd param keep_qs * @access public */ public static function url2uri( $url, $keep_qs = false ) { $url = trim( $url ); $uri = @parse_url( $url, PHP_URL_PATH ); $qs = @parse_url( $url, PHP_URL_QUERY ); if ( ! $keep_qs || ! $qs ) { return $uri; } return $uri . '?' . $qs; } /** * Get attachment relative path to upload folder * * @since 3.0 * @access public * @param string `https://aa.com/bbb/wp-content/upload/2018/08/test.jpg` or `/bbb/wp-content/upload/2018/08/test.jpg` * @return string `2018/08/test.jpg` */ public static function att_short_path( $url ) { if ( ! defined( 'LITESPEED_UPLOAD_PATH' ) ) { $_wp_upload_dir = wp_upload_dir(); $upload_path = self::url2uri( $_wp_upload_dir[ 'baseurl' ] ); define( 'LITESPEED_UPLOAD_PATH', $upload_path ); } $local_file = self::url2uri( $url ); $short_path = substr( $local_file, strlen( LITESPEED_UPLOAD_PATH ) + 1 ); return $short_path; } /** * Make URL to be relative * * NOTE: for subfolder home_url, will keep subfolder part (strip nothing but scheme and host) * * @param string $url * @return string Relative URL, start with / */ public static function make_relative( $url ) { // replace home_url if the url is full url self::domain_const(); if ( strpos( $url, LSCWP_DOMAIN ) === 0 ) { $url = substr( $url, strlen( LSCWP_DOMAIN ) ); } return trim( $url ); } /** * Convert URL to domain only * * @since 1.7.1 */ public static function parse_domain( $url ) { $url = @parse_url( $url ); if ( empty( $url[ 'host' ] ) ) { return ''; } if ( ! empty( $url[ 'scheme' ] ) ) { return $url[ 'scheme' ] . '://' . $url[ 'host' ]; } return '//' . $url[ 'host' ]; } /** * Drop protocol `https:` from https://example.com * * @since 3.3 */ public static function noprotocol( $url ) { $tmp = parse_url( trim( $url ) ); if ( ! empty( $tmp[ 'scheme' ] ) ) { $url = str_replace( $tmp[ 'scheme' ] . ':', '', $url ); } return $url; } /** * Generate domain const * * This will generate http://www.example.com even there is a subfolder in home_url setting * * Conf LSCWP_DOMAIN has NO trailing / * * @since 1.3 * @access public */ public static function domain_const() { if ( defined( 'LSCWP_DOMAIN' ) ) { return; } self::compatibility(); $domain = http_build_url( get_home_url(), array(), HTTP_URL_STRIP_ALL ); define( 'LSCWP_DOMAIN', $domain ); } /** * Array map one textarea to sanitize the url * * @since 1.3 * @access public * @param string $content * @param bool $type String handler type * @return string */ public static function sanitize_lines( $arr, $type = null ) { if ( ! $arr ) { if ( $type === 'string' ) { return ''; } return array(); } if ( ! is_array( $arr ) ) { $arr = explode( "\n", $arr ); } $arr = array_map( 'trim', $arr ); $changed = false; if ( $type === 'uri' ) { $arr = array_map( __CLASS__ . '::url2uri', $arr ); $changed = true; } if ( $type === 'relative' ) { $arr = array_map( __CLASS__ . '::make_relative', $arr );// Remove domain $changed = true; } if ( $type === 'domain' ) { $arr = array_map( __CLASS__ . '::parse_domain', $arr );// Only keep domain $changed = true; } if ( $type === 'noprotocol' ) { $arr = array_map( __CLASS__ . '::noprotocol', $arr ); // Drop protocol, `https://example.com` -> `//example.com` $changed = true; } if ( $changed ) { $arr = array_map( 'trim', $arr ); } $arr = array_unique( $arr ); $arr = array_filter( $arr ); if ( $type === 'string' ) { return implode( "\n", $arr ); } return $arr; } /** * Builds an url with an action and a nonce. * * Assumes user capabilities are already checked. * * @since 1.6 Changed order of 2nd&3rd param, changed 3rd param `append_str` to 2nd `type` * @access public * @return string The built url. */ public static function build_url( $action, $type = false, $is_ajax = false, $page = null, $append_arr = array() ) { $prefix = '?'; if ( $page === '_ori' ) { $page = true; $append_arr[ '_litespeed_ori' ] = 1; } if ( ! $is_ajax ) { if ( $page ) { // If use admin url if ( $page === true ) { $page = 'admin.php'; } else { if ( strpos( $page, '?' ) !== false ) { $prefix = '&'; } } $combined = $page . $prefix . Router::ACTION . '=' . $action; } else { // Current page rebuild URL $params = $_GET; if ( ! empty( $params ) ) { if ( isset( $params[ Router::ACTION ] ) ) { unset( $params[ Router::ACTION ] ); } if ( isset( $params[ '_wpnonce' ] ) ) { unset( $params[ '_wpnonce' ] ); } if ( ! empty( $params ) ) { $prefix .= http_build_query( $params ) . '&'; } } global $pagenow; $combined = $pagenow . $prefix . Router::ACTION . '=' . $action; } } else { $combined = 'admin-ajax.php?action=litespeed_ajax&' . Router::ACTION . '=' . $action; } if ( is_network_admin() ) { $prenonce = network_admin_url( $combined ); } else { $prenonce = admin_url( $combined ); } $url = wp_nonce_url( $prenonce, $action, Router::NONCE ); if ( $type ) { // Remove potential param `type` from url $url = parse_url( htmlspecialchars_decode( $url ) ); parse_str( $url[ 'query' ], $query ); $built_arr = array_merge( $query, array( Router::TYPE => $type ) ); if ( $append_arr ) { $built_arr = array_merge( $built_arr, $append_arr ); } $url[ 'query' ] = http_build_query( $built_arr ); self::compatibility(); $url = http_build_url( $url ); $url = htmlspecialchars( $url, ENT_QUOTES, 'UTF-8' ); } return $url; } /** * Check if the host is the internal host * * @since 1.2.3 * */ public static function internal( $host ) { if ( ! defined( 'LITESPEED_FRONTEND_HOST' ) ) { if ( defined( 'WP_HOME' ) ) { $home_host = WP_HOME;// Also think of `WP_SITEURL` } else { $home_host = get_option( 'home' ); } define( 'LITESPEED_FRONTEND_HOST', parse_url( $home_host, PHP_URL_HOST ) ); } if ( $host === LITESPEED_FRONTEND_HOST ) { return true; } /** * Filter for multiple domains * @since 2.9.4 */ if ( ! isset( self::$_internal_domains ) ) { self::$_internal_domains = apply_filters( 'litespeed_internal_domains', array() ); } if ( self::$_internal_domains ) { return in_array( $host, self::$_internal_domains ); } return false; } /** * Check if an URL is a internal existing file * * @since 1.2.2 * @since 1.6.2 Moved here from optm.cls due to usage of media.cls * @access public * @return string|bool The real path of file OR false */ public static function is_internal_file( $url, $addition_postfix = false ) { if ( substr( $url, 0, 5 ) == 'data:' ) { Debug2::debug2( '[Util] data: content not file' ); return false; } $url_parsed = parse_url( $url ); if ( isset( $url_parsed[ 'host' ] ) && ! self::internal( $url_parsed[ 'host' ] ) ) { // Check if is cdn path // Do this to avoid user hardcoded src in tpl if ( ! CDN::internal( $url_parsed[ 'host' ] ) ) { Debug2::debug2( '[Util] external' ); return false; } } if ( empty( $url_parsed[ 'path' ] ) ) { return false; } // Need to replace child blog path for assets, ref: .htaccess if ( is_multisite() && defined( 'PATH_CURRENT_SITE' ) ) { $pattern = '#^' . PATH_CURRENT_SITE . '([_0-9a-zA-Z-]+/)(wp-(content|admin|includes))#U'; $replacement = PATH_CURRENT_SITE . '$2'; $url_parsed[ 'path' ] = preg_replace( $pattern, $replacement, $url_parsed[ 'path' ] ); // $current_blog = (int) get_current_blog_id(); // $main_blog_id = (int) get_network()->site_id; // if ( $current_blog === $main_blog_id ) { // define( 'LITESPEED_IS_MAIN_BLOG', true ); // } // else { // define( 'LITESPEED_IS_MAIN_BLOG', false ); // } } // Parse file path /** * Trying to fix pure /.htaccess rewrite to /wordpress case * * Add `define( 'LITESPEED_WP_REALPATH', '/wordpress' );` in wp-config.php in this case * * @internal #611001 - Combine & Minify not working? * @since 1.6.3 */ if ( substr( $url_parsed[ 'path' ], 0, 1 ) === '/' ) { if ( defined( 'LITESPEED_WP_REALPATH' ) ) { $file_path_ori = $_SERVER[ 'DOCUMENT_ROOT' ] . LITESPEED_WP_REALPATH . $url_parsed[ 'path' ]; } else { $file_path_ori = $_SERVER[ 'DOCUMENT_ROOT' ] . $url_parsed[ 'path' ]; } } else { $file_path_ori = Router::frontend_path() . '/' . $url_parsed[ 'path' ]; } /** * Added new file postfix to be check if passed in * @since 2.2.4 */ if ( $addition_postfix ) { $file_path_ori .= '.' . $addition_postfix; } /** * Added this filter for those plugins which overwrite the filepath * @see #101091 plugin `Hide My WordPress` * @since 2.2.3 */ $file_path_ori = apply_filters( 'litespeed_realpath', $file_path_ori ); $file_path = realpath( $file_path_ori ); if ( ! is_file( $file_path ) ) { Debug2::debug2( '[Util] file not exist: ' . $file_path_ori ); return false; } return array( $file_path, filesize( $file_path ) ); } /** * Safely parse URL for v5.3 compatibility * * @since 3.4.3 */ public static function parse_url_safe( $url, $component = -1 ) { if ( substr( $url, 0, 2 ) == '//' ) { $url = 'https:' . $url; } return parse_url( $url, $component ); } /** * Replace url in srcset to new value * * @since 2.2.3 */ public static function srcset_replace( $content, $callback ) { preg_match_all( '# srcset=([\'"])(.+)\g{1}#iU', $content, $matches ); $srcset_ori = array(); $srcset_final = array(); foreach ( $matches[ 2 ] as $k => $urls_ori ) { $urls_final = explode( ',', $urls_ori ); $changed = false; foreach ( $urls_final as $k2 => $url_info ) { $url_info_arr = explode( ' ', trim( $url_info ) ); if ( ! $url2 = call_user_func( $callback, $url_info_arr[ 0 ] ) ) { continue; } $changed = true; $urls_final[ $k2 ] = str_replace( $url_info_arr[ 0 ], $url2, $url_info ); Debug2::debug2( '[Util] - srcset replaced to ' . $url2 . ( ! empty( $url_info_arr[ 1 ] ) ? ' ' . $url_info_arr[ 1 ] : '' ) ); } if ( ! $changed ) { continue; } $urls_final = implode( ',', $urls_final ); $srcset_ori[] = $matches[ 0 ][ $k ]; $srcset_final[] = str_replace( $urls_ori, $urls_final, $matches[ 0 ][ $k ] ); } if ( $srcset_ori ) { $content = str_replace( $srcset_ori, $srcset_final, $content ); Debug2::debug2( '[Util] - srcset replaced' ); } return $content; } /** * Generate pagination * * @since 3.0 * @access public */ public static function pagination( $total, $limit, $return_offset = false ) { $pagenum = isset( $_GET[ 'pagenum' ] ) ? absint( $_GET[ 'pagenum' ] ) : 1; $offset = ( $pagenum - 1 ) * $limit; $num_of_pages = ceil( $total / $limit ); if ( $offset > $total ) { $offset = $total - $limit; } if ( $offset < 0 ) { $offset = 0; } if ( $return_offset ) { return $offset; } $page_links = paginate_links( array( 'base' => add_query_arg( 'pagenum', '%#%' ), 'format' => '', 'prev_text' => '«', 'next_text' => '»', 'total' => $num_of_pages, 'current' => $pagenum, ) ); return '
' . $page_links . '
'; } /** * Generate placeholder for an array to query * * @since 2.0 * @access public */ public static function chunk_placeholder( $data, $fields ) { $division = substr_count( $fields, ',' ) + 1; $q = implode( ',', array_map( function( $el ) { return '(' . implode( ',', $el ) . ')'; }, array_chunk( array_fill( 0, count( $data ), '%s' ), $division ) ) ); return $q; } }