* * @since 2.11 */ public function warning_critical_css_dir_permissions() { if ( current_user_can( 'rocket_manage_options' ) && ( ! $this->filesystem->is_writable( WP_ROCKET_CRITICAL_CSS_PATH ) ) && ( $this->options->get( 'async_css', false ) ) && rocket_valid_key() ) { $boxes = get_user_meta( get_current_user_id(), 'rocket_boxes', true ); if ( in_array( __FUNCTION__, (array) $boxes, true ) ) { return; } $message = rocket_notice_writing_permissions( trim( str_replace( ABSPATH, '', WP_ROCKET_CRITICAL_CSS_PATH ), '/' ) ); rocket_notice_html( [ 'status' => 'error', 'dismissible' => '', 'message' => $message, ] ); } } /** * Insert loadCSS script in . * * @since 2.11.2 Updated loadCSS rel=preload polyfill to version 2.0.1 * @since 2.10 */ public function insert_load_css() { if ( ! $this->should_async_css() ) { return; } // This filter is documented in inc/classes/Buffer/class-tests.php. $rocket_cache_search = apply_filters( 'rocket_cache_search', false ); // Don't apply on search page. if ( is_search() && ! $rocket_cache_search ) { return; } // Don't apply on 404 page. if ( is_404() ) { return; } if ( empty( $this->critical_css->get_current_page_critical_css() ) && empty( $this->options->get( 'critical_css', '' ) ) ) { return; } echo /* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Dynamic content is properly escaped in the view. */ << /*! loadCSS rel=preload polyfill. [c]2017 Filament Group, Inc. MIT License */ (function(w){"use strict";if(!w.loadCSS){w.loadCSS=function(){}} var rp=loadCSS.relpreload={};rp.support=(function(){var ret;try{ret=w.document.createElement("link").relList.supports("preload")}catch(e){ret=!1} return function(){return ret}})();rp.bindMediaToggle=function(link){var finalMedia=link.media||"all";function enableStylesheet(){link.media=finalMedia} if(link.addEventListener){link.addEventListener("load",enableStylesheet)}else if(link.attachEvent){link.attachEvent("onload",enableStylesheet)} setTimeout(function(){link.rel="stylesheet";link.media="only x"});setTimeout(enableStylesheet,3000)};rp.poly=function(){if(rp.support()){return} var links=w.document.getElementsByTagName("link");for(var i=0;i JS; } /** * Insert critical CSS before combined CSS when option is active. * * @since 2.11.5 * * @param string $buffer HTML output of the page. * * @return string Updated HTML output */ public function insert_critical_css_buffer( $buffer ) { if ( ! $this->should_async_css() ) { return $buffer; } $critical_css_content = $this->critical_css->get_critical_css_content(); if ( empty( $critical_css_content ) ) { return $buffer; } $critical_css_content = str_replace( '\\', '\\\\', $critical_css_content ); $buffer = preg_replace( '##iU', '', $buffer, 1 ); return preg_replace( '##iU', $this->return_remove_cpcss_script() . '', $buffer, 1 ); } /** * Returns JS script to remove the critical css style from frontend. * * @since 3.6 * * @return string */ protected function return_remove_cpcss_script() { $filename = rocket_get_constant( 'SCRIPT_DEBUG' ) ? 'cpcss-removal.js' : 'cpcss-removal.min.js'; $script = rocket_get_constant( 'WP_ROCKET_PATH' ) . "assets/js/{$filename}"; if ( ! is_readable( $script ) ) { return ''; } return sprintf( '', $this->filesystem->get_contents( $script ) ); } /** * Adds wprRemoveCPCSS to excluded inline JS array. * * @since 3.6 * * @param array $excluded_inline Array of inline JS excluded from being combined. * * @return array */ public function exclude_inline_js( array $excluded_inline ) { $excluded_inline[] = 'wprRemoveCPCSS'; return $excluded_inline; } /** * Defer loading of CSS files. * * @since 2.10 * * @param string $buffer HTML code. * * @return string Updated HTML code */ public function async_css( $buffer ) { if ( ! $this->should_async_css() ) { return $buffer; } if ( empty( $this->critical_css->get_current_page_critical_css() ) && empty( $this->options->get( 'critical_css', '' ) ) ) { return $buffer; } $excluded_css = array_flip( $this->critical_css->get_exclude_async_css() ); /** * Filters the pattern used to get all stylesheets in the HTML. * * @since 2.10 * * @param string $css_pattern Regex pattern to get all stylesheets in the HTML. */ $css_pattern = apply_filters( 'rocket_async_css_regex_pattern', '/(?=]*\s(rel\s*=\s*[\'"]stylesheet["\']))]*\shref\s*=\s*[\'"]([^\'"]+)[\'"](.*)>/iU' ); // Get all css files with this regex. preg_match_all( $css_pattern, $buffer, $tags_match ); if ( ! isset( $tags_match[0] ) ) { return $buffer; } $noscripts = ''; return str_replace( '', $noscripts . '', $buffer ); } /** * Regenerates the CPCSS when switching theme if the option is active. * * @since 3.3 */ public function maybe_regenerate_cpcss() { if ( ! $this->options->get( 'async_css' ) ) { return; } $this->critical_css->process_handler(); } /** * Maybe disable adding the preload fonts links * * @since 3.8.8 * * @return bool */ public function maybe_disable_preload_fonts() : bool { if ( ! $this->should_async_css() ) { return false; } return ( ! empty( $this->options->get( 'critical_css', '' ) ) || ! empty( $this->critical_css->get_current_page_critical_css() ) ); } /** * Checks if mobile CPCSS is active. * * @since 3.6 * * @return boolean CPCSS active or not. */ private function is_mobile_cpcss_active() { return ( $this->options->get( 'async_css', 0 ) && $this->options->get( 'cache_mobile', 0 ) && $this->options->get( 'do_caching_mobile_files', 0 ) ) && $this->options->get( 'async_css_mobile', 0 ); } /** * Checks if we should async CSS * * @since 3.6.2.1 * * @return boolean */ private function should_async_css() { if ( rocket_get_constant( 'DONOTROCKETOPTIMIZE' ) ) { return false; } if ( ! $this->options->get( 'async_css', 0 ) ) { return false; } return ! is_rocket_post_excluded_option( 'async_css' ); } }