_faces ) ) { return $html; } $urls = []; foreach ( $font_faces as $font_face ) { if ( empty( $font_face['content'] ) ) { continue; } $font_url = $this->extract_first_font( $font_face['content'] ); /** * Filters font URL with CDN hostname * * @since 3.11.4 * * @param type $url url to be rewritten. */ $font_url = apply_filters( 'rocket_font_url', $font_url ); if ( empty( $font_url ) ) { continue; } $urls[] = $font_url; } if ( empty( $urls ) ) { return $html; } $urls = array_unique( $urls ); $replace = preg_replace( '##iU', '' . $this->preload_links( $urls ), $html, 1 ); if ( null === $replace ) { return $html; } return $replace; } /** * Remove preconnect tag for google api. * * @param string $html html content. * * @return string */ protected function remove_google_font_preconnect( string $html ): string { $clean_html = $this->hide_comments( $html ); $clean_html = $this->hide_noscripts( $clean_html ); $clean_html = $this->hide_scripts( $clean_html ); $links = $this->find( ']+[\s"\'])?rel\s*=\s*[\'"]((preconnect)|(dns-prefetch))[\'"]([^>]+)?\/?>', $clean_html, 'Uis' ); foreach ( $links as $link ) { if ( preg_match( '/href=[\'"](https:)?\/\/fonts.googleapis.com\/?[\'"]/', $link[0] ) ) { $html = str_replace( $link[0], '', $html ); } } return $html; } /** * Extracts the first font URL from the font-face declaration * * Skips .eot fonts if it exists * * @since 3.11 * * @param string $font_face Font-face declaration content. * * @return string */ private function extract_first_font( string $font_face ): string { if ( ! preg_match_all( '/src:\s*(?[^;}]*)/is', $font_face, $sources, PREG_SET_ORDER ) ) { return ''; } foreach ( $sources as $src ) { if ( empty( $src['urls'] ) ) { continue; } $urls = explode( ',', $src['urls'] ); foreach ( $urls as $url ) { if ( false !== strpos( $url, '.eot' ) ) { continue; } if ( ! preg_match( '/url\(\s*[\'"]?(?[^\'")]+)[\'"]?\)/is', $url, $matches ) ) { continue; } return trim( $matches['url'] ); } } return ''; } /** * Converts an array of URLs to preload link tags * * @param array $urls An array of URLs. * * @return string */ private function preload_links( array $urls ): string { $links = ''; foreach ( $urls as $url ) { $links .= ''; } return $links; } /** * Set Rucss inline attr exclusions * * @return void */ private function set_inline_exclusions_lists() { $wpr_dynamic_lists = $this->data_manager->get_lists(); $this->inline_atts_exclusions = isset( $wpr_dynamic_lists->rucss_inline_atts_exclusions ) ? $wpr_dynamic_lists->rucss_inline_atts_exclusions : []; $this->inline_content_exclusions = isset( $wpr_dynamic_lists->rucss_inline_content_exclusions ) ? $wpr_dynamic_lists->rucss_inline_content_exclusions : []; } /** * Displays a notice if the used CSS folder is not writable * * @since 3.11.4 * * @return void */ public function notice_write_permissions() { if ( ! current_user_can( 'rocket_manage_options' ) ) { return; } if ( ! $this->is_enabled() ) { return; } if ( $this->filesystem->is_writable_folder() ) { return; } $message = rocket_notice_writing_permissions( trim( str_replace( rocket_get_constant( 'ABSPATH', '' ), '', rocket_get_constant( 'WP_ROCKET_USED_CSS_PATH', '' ) ), '/' ) ); rocket_notice_html( [ 'status' => 'error', 'dismissible' => '', 'message' => $message, ] ); } /** * Validate the items in array to be strings only and preg_quote them. * * @param array $items Array to be validated and quoted. * * @return array|string[] */ private function validate_array_and_quote( array $items ) { $items_array = array_filter( $items, 'is_string' ); return array_map( static function ( $item ) { return preg_quote( $item, '/' ); }, $items_array ); } }