config = $config; } /** * Runs User Experience Remove CSS/JS Mutator. * * @since 2.7.0 * * @param string $buffer Buffer string containing browser output. * * @return string */ public function run( $buffer ) { $r = apply_filters( 'w3tc_remove_cssjs_mutator_before', array( 'buffer' => $buffer, ) ); $this->buffer = $r['buffer']; // Sets includes whose matches will be stripped site-wide. $this->includes = $this->config->get_array( array( 'user-experience-remove-cssjs', 'includes', ) ); // Sets singles includes data whose matches will be removed on mated pages. $this->singles_includes = $this->config->get_array( 'user-experience-remove-cssjs-singles' ); // If old data structure convert to new. // Old data structure used url_pattern as the key for each block. New uses indicies and has url_pattern within. if ( ! is_numeric( key( $this->singles_includes ) ) ) { $new_array = array(); foreach ( $this->singles_includes as $match => $data ) { $new_array[] = array( 'url_pattern' => $match, 'action' => isset( $data['action'] ) ? $data['action'] : 'exclude', 'includes' => $data['includes'], 'includes_content' => $data['includes_content'], ); } $this->singles_includes = $new_array; } $this->buffer = preg_replace_callback( '~(]+href[^>]+>)|(]+src[^>]+>)~is', array( $this, 'remove_content' ), $this->buffer ); return $this->buffer; } /** * Removes matched link/script tag from HTML content. * * @since 2.7.0 * * @param array $matches array of matched CSS/JS entries. * * @return string */ public function remove_content( $matches ) { $content = $matches[0]; if ( is_main_query() && $this->is_content_included( $content ) ) { return ''; } return $content; } /** * Checks if content matches defined rules for exlusion/inclusion. * * @since 2.7.0 * * @param string $content script tag string. * * @return boolean */ private function is_content_included( $content ) { global $wp; // Always removes matched CSS/JS for home page. if ( is_front_page() ) { foreach ( $this->includes as $include ) { if ( ! empty( $include ) ) { if ( strpos( $content, $include ) !== false ) { return true; } } } } // Build array of possible current page URLs. $current_pages = array( esc_url( trailingslashit( home_url( $wp->request ) ) ), ); if ( ! empty( $_SERVER['REQUEST_URI'] ) ) { $current_pages[] = esc_url( trailingslashit( home_url( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) ) ); } foreach ( $this->singles_includes as $id => $data ) { // Check if the defined single CSS/JS file is present in HTML content. if ( ! empty( $data ) && strpos( $content, $data['url_pattern'] ) !== false ) { // Check if current page URL(s) match any defined conditions. $page_match = Util_Environment::array_intersect_partial( $current_pages, $data['includes'] ); // Check if current page content match any defined conditions. $content_match = false; foreach ( $data['includes_content'] as $include ) { if ( strpos( $this->buffer, $include ) !== false ) { $content_match = true; break; } } /** * If set to exclude, remove the file if the page matches defined URLs. * If set to include, Remove the file if the page doesn't match defined URLs. */ if ( 'exclude' === $data['action'] && ( $page_match || $content_match ) ) { return true; } elseif ( 'include' === $data['action'] && ! ( $page_match || $content_match ) ) { return true; } } } return false; } }