fetch_options();
}
$this->options = $options;
}
public function run()
{
if ( is_admin() ) {
add_action( 'admin_menu', array( $this, 'admin_menu' ) );
add_filter( 'autoptimize_filter_settingsscreen_tabs', array( $this, 'add_extra_tab' ) );
} else {
$this->run_on_frontend();
}
}
protected function fetch_options()
{
$value = get_option( 'autoptimize_extra_settings' );
if ( empty( $value ) ) {
// Fallback to returning defaults when no stored option exists yet.
$value = autoptimizeConfig::get_ao_extra_default_options();
}
// get service availability.
$value['availabilities'] = get_option( 'autoptimize_service_availablity' );
if ( empty( $value['availabilities'] ) ) {
$value['availabilities'] = autoptimizeUtils::check_service_availability( true );
}
return $value;
}
public function disable_emojis()
{
// Removing all actions related to emojis!
remove_action( 'admin_print_styles', 'print_emoji_styles' );
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
remove_action( 'wp_print_styles', 'print_emoji_styles' );
remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
// Removes TinyMCE emojis.
add_filter( 'tiny_mce_plugins', array( $this, 'filter_disable_emojis_tinymce' ) );
// Removes emoji dns-preftech.
add_filter( 'wp_resource_hints', array( $this, 'filter_remove_emoji_dns_prefetch' ), 10, 2 );
}
public function filter_disable_emojis_tinymce( $plugins )
{
if ( is_array( $plugins ) ) {
return array_diff( $plugins, array( 'wpemoji' ) );
} else {
return array();
}
}
public function filter_remove_qs( $src ) {
if ( strpos( $src, '?ver=' ) ) {
$src = remove_query_arg( 'ver', $src );
}
return $src;
}
public function extra_async_js( $in )
{
$exclusions = array();
if ( ! empty( $in ) ) {
$exclusions = array_fill_keys( array_filter( array_map( 'trim', explode( ',', $in ) ) ), '' );
}
$settings = $this->options['autoptimize_extra_text_field_3'];
$async = array_fill_keys( array_filter( array_map( 'trim', explode( ',', $settings ) ) ), '' );
$attr = apply_filters( 'autoptimize_filter_extra_async', 'async' );
foreach ( $async as $k => $v ) {
$async[ $k ] = $attr;
}
// Merge exclusions & asyncs in one array and return to AO API.
$merged = array_merge( $exclusions, $async );
return $merged;
}
protected function run_on_frontend()
{
$options = $this->options;
// Disable emojis if specified.
if ( ! empty( $options['autoptimize_extra_checkbox_field_1'] ) ) {
$this->disable_emojis();
}
// Remove version query parameters.
if ( ! empty( $options['autoptimize_extra_checkbox_field_0'] ) ) {
add_filter( 'script_loader_src', array( $this, 'filter_remove_qs' ), 15, 1 );
add_filter( 'style_loader_src', array( $this, 'filter_remove_qs' ), 15, 1 );
}
// Making sure is_plugin_active() exists when we need it.
if ( ! function_exists( 'is_plugin_active' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
// Avoiding conflicts of interest when async-javascript plugin is active!
$async_js_plugin_active = false;
if ( function_exists( 'is_plugin_active' ) && is_plugin_active( 'async-javascript/async-javascript.php' ) ) {
$async_js_plugin_active = true;
}
if ( ! empty( $options['autoptimize_extra_text_field_3'] ) && ! $async_js_plugin_active ) {
add_filter( 'autoptimize_filter_js_exclude', array( $this, 'extra_async_js' ), 10, 1 );
}
// Optimize google fonts!
if ( ! empty( $options['autoptimize_extra_radio_field_4'] ) && ( '1' !== $options['autoptimize_extra_radio_field_4'] ) ) {
add_filter( 'wp_resource_hints', array( $this, 'filter_remove_gfonts_dnsprefetch' ), 10, 2 );
add_filter( 'autoptimize_html_after_minify', array( $this, 'filter_optimize_google_fonts' ), 10, 1 );
add_filter( 'autoptimize_extra_filter_tobepreconn', array( $this, 'filter_preconnect_google_fonts' ), 10, 1 );
}
// Preconnect!
if ( ! empty( $options['autoptimize_extra_text_field_2'] ) || has_filter( 'autoptimize_extra_filter_tobepreconn' ) ) {
add_filter( 'wp_resource_hints', array( $this, 'filter_preconnect' ), 10, 2 );
}
// Optimize Images kicks in if;
// * the option is activated by user.
// * imgopt user stats does not have status -2.
// * imgopt status is not "down".
// * imgopt status is not "launch" or imgopt_launch_ok() returns be true.
$_do_cdn = true;
$_userstatus = $this->get_imgopt_provider_userstatus();
if ( -2 == $_userstatus['Status'] ) {
$_do_cdn = false;
}
if ( ! empty( $options['autoptimize_extra_checkbox_field_5'] ) && $_do_cdn && 'down' !== $options['availabilities']['extra_imgopt']['status'] && ( 'launch' !== $options['availabilities']['extra_imgopt']['status'] || $this->imgopt_launch_ok() ) ) {
if ( apply_filters( 'autoptimize_filter_extra_imgopt_do', true ) ) {
add_filter( 'autoptimize_html_after_minify', array( $this, 'filter_optimize_images' ), 10, 1 );
$_imgopt_active = true;
}
if ( apply_filters( 'autoptimize_filter_extra_imgopt_do_css', true ) ) {
add_filter( 'autoptimize_filter_base_replace_cdn', array( $this, 'filter_optimize_css_images' ), 10, 1 );
$_imgopt_active = true;
}
if ( $_imgopt_active ) {
add_filter( 'autoptimize_extra_filter_tobepreconn', array( $this, 'filter_preconnect_imgopt_url' ), 10, 1 );
}
}
}
public function filter_remove_emoji_dns_prefetch( $urls, $relation_type )
{
$emoji_svg_url = apply_filters( 'emoji_svg_url', 'https://s.w.org/images/core/emoji/' );
return $this->filter_remove_dns_prefetch( $urls, $relation_type, $emoji_svg_url );
}
public function filter_remove_gfonts_dnsprefetch( $urls, $relation_type )
{
return $this->filter_remove_dns_prefetch( $urls, $relation_type, 'fonts.googleapis.com' );
}
public function filter_remove_dns_prefetch( $urls, $relation_type, $url_to_remove )
{
if ( 'dns-prefetch' === $relation_type ) {
$cnt = 0;
foreach ( $urls as $url ) {
if ( false !== strpos( $url, $url_to_remove ) ) {
unset( $urls[ $cnt ] );
}
$cnt++;
}
}
return $urls;
}
public function filter_optimize_google_fonts( $in )
{
// Extract fonts, partly based on wp rocket's extraction code.
$markup = preg_replace( '//Uis', '', $in );
preg_match_all( '#])+)?(?:\s+href\s*=\s*([\'"])((?:https?:)?\/\/fonts\.googleapis\.com\/css(?:(?!\1).)+)\1)(?:\s+[^>]*)?>#iU', $markup, $matches );
$fonts_collection = array();
if ( ! $matches[2] ) {
return $in;
}
// Store them in $fonts array.
$i = 0;
foreach ( $matches[2] as $font ) {
if ( ! preg_match( '/rel=["\']dns-prefetch["\']/', $matches[0][ $i ] ) ) {
// Get fonts name.
$font = str_replace( array( '%7C', '%7c' ), '|', $font );
$font = explode( 'family=', $font );
$font = ( isset( $font[1] ) ) ? explode( '&', $font[1] ) : array();
// Add font to $fonts[$i] but make sure not to pollute with an empty family!
$_thisfont = array_values( array_filter( explode( '|', reset( $font ) ) ) );
if ( ! empty( $_thisfont ) ) {
$fonts_collection[ $i ]['fonts'] = $_thisfont;
// And add subset if any!
$subset = ( is_array( $font ) ) ? end( $font ) : '';
if ( false !== strpos( $subset, 'subset=' ) ) {
$subset = str_replace( array( '%2C', '%2c' ), ',', $subset );
$subset = explode( 'subset=', $subset );
$fonts_collection[ $i ]['subsets'] = explode( ',', $subset[1] );
}
}
// And remove Google Fonts.
$in = str_replace( $matches[0][ $i ], '', $in );
}
$i++;
}
$options = $this->options;
$fonts_markup = '';
if ( '2' === $options['autoptimize_extra_radio_field_4'] ) {
// Remove Google Fonts.
unset( $fonts_collection );
return $in;
} elseif ( '3' === $options['autoptimize_extra_radio_field_4'] || '5' === $options['autoptimize_extra_radio_field_4'] ) {
// Aggregate & link!
$fonts_string = '';
$subset_string = '';
foreach ( $fonts_collection as $font ) {
$fonts_string .= '|' . trim( implode( '|', $font['fonts'] ), '|' );
if ( ! empty( $font['subsets'] ) ) {
$subset_string .= ',' . trim( implode( ',', $font['subsets'] ), ',' );
}
}
if ( ! empty( $subset_string ) ) {
$subset_string = str_replace( ',', '%2C', ltrim( $subset_string, ',' ) );
$fonts_string = $fonts_string . '&subset=' . $subset_string;
}
$fonts_string = str_replace( '|', '%7C', ltrim( $fonts_string, '|' ) );
if ( ! empty( $fonts_string ) ) {
if ( '5' === $options['autoptimize_extra_radio_field_4'] ) {
$rel_string = 'rel="preload" as="style" onload="' . autoptimizeConfig::get_ao_css_preload_onload() . '"';
} else {
$rel_string = 'rel="stylesheet"';
}
$fonts_markup = '';
}
} elseif ( '4' === $options['autoptimize_extra_radio_field_4'] ) {
// Aggregate & load async (webfont.js impl.)!
$fonts_array = array();
foreach ( $fonts_collection as $_fonts ) {
if ( ! empty( $_fonts['subsets'] ) ) {
$_subset = implode( ',', $_fonts['subsets'] );
foreach ( $_fonts['fonts'] as $key => $_one_font ) {
$_one_font = $_one_font . ':' . $_subset;
$_fonts['fonts'][ $key ] = $_one_font;
}
}
$fonts_array = array_merge( $fonts_array, $_fonts['fonts'] );
}
$fonts_markup = '';
}
// Replace back in markup.
$out = substr_replace( $in, $fonts_markup . '', $preload_polyfill . '