Completed
Push — master ( ffe98c...4b0354 )
by frank
01:54
created

autoptimizeExtra.php ➔ disable_emojis_remove_dns_prefetch()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 9
nc 2
nop 2
dl 0
loc 14
rs 9.2
c 0
b 0
f 0
1
<?php
2
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
4
// initialize
5
if ( is_admin() ) {
6
    add_action( 'admin_menu', 'autoptimize_extra_admin' );
7
    add_filter( 'autoptimize_filter_settingsscreen_tabs','add_autoptimize_extra_tab' );
8
} else {
9
    autoptimize_extra_init();
10
}
11
12
// get option
13
function autoptimize_extra_get_options() {
14
    $_default_val = array("autoptimize_extra_checkbox_field_1"=>"0","autoptimize_extra_checkbox_field_0"=>"0","autoptimize_extra_radio_field_4"=>"1","autoptimize_extra_text_field_2"=>"","autoptimize_extra_text_field_3"=>"");
15
    $_option_val = get_option( 'autoptimize_extra_settings' );
16
    if (empty($_option_val)) {
17
        $_option_val = $_default_val;
18
    }
19
    return $_option_val;
20
}
21
22
// frontend init
23
function autoptimize_extra_init() {
24
    $autoptimize_extra_options = autoptimize_extra_get_options();
25
26
    /* disable emojis */
27
    if ( !empty($autoptimize_extra_options['autoptimize_extra_checkbox_field_1']) ) {
28
        autoptimize_extra_disable_emojis();
29
    }
30
    
31
    /* remove version from query string */
32
    if ( !empty($autoptimize_extra_options['autoptimize_extra_checkbox_field_0']) ) {
33
        add_filter( 'script_loader_src', 'autoptimize_extra_remove_qs', 15, 1 );
34
        add_filter( 'style_loader_src', 'autoptimize_extra_remove_qs', 15, 1 );
35
    }
36
37
    /* async JS */
38
    if (!empty($autoptimize_extra_options['autoptimize_extra_text_field_3'])) {
39
        add_filter('autoptimize_filter_js_exclude','autoptimize_extra_async_js',10,1);
40
    }
41
42
    /* optimize google fonts */
43
    if ( !empty( $autoptimize_extra_options['autoptimize_extra_radio_field_4'] ) && ( $autoptimize_extra_options['autoptimize_extra_radio_field_4'] != "1" ) ) {
44
        if ( $autoptimize_extra_options['autoptimize_extra_radio_field_4'] == "2" ) {
45
            add_filter('autoptimize_filter_css_removables','autoptimize_extra_remove_gfonts',10,1);
46
        } else {
47
            add_filter('autoptimize_html_after_minify','autoptimize_extra_gfonts',10,1);
48
            add_filter('autoptimize_extra_filter_tobepreconn','autoptimize_extra_preconnectgooglefonts',10,1);
49
        }
50
    }
51
    
52
    /* preconnect */
53
    if ( !empty($autoptimize_extra_options['autoptimize_extra_text_field_2']) || has_filter('autoptimize_extra_filter_tobepreconn') ) {
54
        add_filter( 'wp_resource_hints', 'autoptimize_extra_preconnect', 10, 2 );
55
    }
56
}
57
58
// disable emoji's functions
59
function autoptimize_extra_disable_emojis() {
60
    // all actions related to emojis
61
    remove_action( 'admin_print_styles', 'print_emoji_styles' );
62
    remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
63
    remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
64
    remove_action( 'wp_print_styles', 'print_emoji_styles' );
65
    remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
66
    remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
67
    remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
68
69
    // filter to remove TinyMCE emojis
70
    add_filter( 'tiny_mce_plugins', 'autoptimize_extra_disable_emojis_tinymce' );
71
72
    // and remove dns-prefetch for emoji
73
    add_filter( 'wp_resource_hints', 'disable_emojis_remove_dns_prefetch', 10, 2 );
74
}
75
76
function autoptimize_extra_disable_emojis_tinymce( $plugins ) {
77
    if ( is_array( $plugins ) ) {
78
        return array_diff( $plugins, array( 'wpemoji' ) );
79
    } else {
80
        return array();
81
    }
82
}
83
84
function disable_emojis_remove_dns_prefetch( $urls, $relation_type ) {
85
    if ( 'dns-prefetch' == $relation_type ) {
86
        $_count=0;
87
        $_emoji_svg_url = apply_filters( 'emoji_svg_url', 'https://s.w.org/images/core/emoji/' );
88
        foreach ($urls as $_url) {
89
            if ( strpos($_url,$_emoji_svg_url) !== false ) {
90
                unset($urls[$_count]);
91
            }
92
            $_count++;
93
        }
94
    }
95
96
    return $urls;
97
}
98
99
// remove query string function
100
function autoptimize_extra_remove_qs( $src ) {
101
    if ( strpos($src, '?ver=') ) {
102
            $src = remove_query_arg( 'ver', $src );
103
    }
104
    return $src;
105
}
106
107
// async function
108
function autoptimize_extra_async_js($in) {
109
    $autoptimize_extra_options = autoptimize_extra_get_options();
110
    
111
    // get exclusions
112
    $AO_JSexclArrayIn = array();
113 View Code Duplication
    if (!empty($in)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
114
        $AO_JSexclArrayIn = array_fill_keys(array_filter(array_map('trim',explode(",",$in))),"");
115
    }
116
    
117
    // get asyncs
118
    $_fromSetting = $autoptimize_extra_options['autoptimize_extra_text_field_3'];
119
    $AO_asynced_JS = array_fill_keys(array_filter(array_map('trim',explode(",",$_fromSetting))),"");
120
    foreach ($AO_asynced_JS as $JSkey => $JSvalue) {
121
        $AO_asynced_JS[$JSkey] = "async";
122
    }
123
    
124
    // merge exclusions & asyncs in one array and return to AO API
125
    $AO_excl_w_async = array_merge( $AO_JSexclArrayIn, $AO_asynced_JS );
126
    return $AO_excl_w_async;
127
}
128
129
// preconnect function
130
function autoptimize_extra_preconnect($hints, $relation_type) {
131
    $autoptimize_extra_options = autoptimize_extra_get_options();
132
    
133
    // get setting and store in array
134
    $_to_be_preconnected = array_filter(array_map('trim',explode(",",$autoptimize_extra_options['autoptimize_extra_text_field_2'])));
135
    $_to_be_preconnected = apply_filters( 'autoptimize_extra_filter_tobepreconn', $_to_be_preconnected );
136
137
    // walk array, extract domain and add to new array with crossorigin attribute
138
    foreach ($_to_be_preconnected as $_preconn_single) {
139
        $_preconn_parsed = parse_url($_preconn_single);
140
        
141
        if ( is_array($_preconn_parsed) && empty($_preconn_parsed['scheme']) ) {
142
            $_preconn_domain = "//".$_preconn_parsed['host'];
143
        } else if ( is_array($_preconn_parsed) ) {
144
            $_preconn_domain = $_preconn_parsed['scheme']."://".$_preconn_parsed['host'];
145
        }
146
        
147
        if ( !empty($_preconn_domain) ) {
148
            $_preconn_hint = array('href' => $_preconn_domain);
149
            // fonts don't get preconnected unless crossorigin flag is set, non-fonts don't get preconnected if origin flag is set
150
            // so hardcode fonts.gstatic.com to come with crossorigin and have filter to add other domains if needed
151
            $_preconn_crossorigin = apply_filters( 'autoptimize_extra_filter_preconn_crossorigin', array('https://fonts.gstatic.com') );
152
            if ( in_array( $_preconn_domain, $_preconn_crossorigin ) ) {
153
                $_preconn_hint['crossorigin'] = 'anonymous';
154
            }
155
            $_new_hints[] = $_preconn_hint;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$_new_hints was never initialized. Although not strictly required by PHP, it is generally a good practice to add $_new_hints = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
156
        }
157
    }
158
159
    // merge in wordpress' preconnect hints
160
    if ( 'preconnect' === $relation_type && !empty($_new_hints) ) {
161
        $hints = array_merge($hints, $_new_hints);      
162
    }
163
    
164
    return $hints;
165
}
166
167
// google font functions
168
function autoptimize_extra_remove_gfonts($in) { 
169
    // simply remove google fonts
170
    return $in.", fonts.googleapis.com"; 
171
}
172
173
function autoptimize_extra_gfonts($in) {
174
    $autoptimize_extra_options = autoptimize_extra_get_options();
175
    
176
    // extract fonts, partly based on wp rocket's extraction code
177
    $_without_comments = preg_replace( '/<!--(.*)-->/Uis', '', $in );
178
    preg_match_all( '#<link(?:\s+(?:(?!href\s*=\s*)[^>])+)?(?:\s+href\s*=\s*([\'"])((?:https?:)?\/\/fonts\.googleapis\.com\/css(?:(?!\1).)+)\1)(?:\s+[^>]*)?>#iU', $_without_comments, $matches );
179
180
    $i = 0;
181
    $fontsCollection = array();
182
    if ( ! $matches[2] ) {
183
        return $in;
184
    }
185
    
186
    // store them in $fonts array
187
    foreach ( $matches[2] as $font ) {
188
        if ( ! preg_match( '/rel=["\']dns-prefetch["\']/', $matches[0][ $i ] ) ) {
189
            // Get fonts name.
190
            $font = str_replace( array( '%7C', '%7c' ) , '|', $font );
191
            $font = explode( 'family=', $font );
192
            $font = ( isset( $font[1] ) ) ? explode( '&', $font[1] ) : array();
193
            // Add font to $fonts[$i] but make sure not to pollute with an empty family
194
            $_thisfont = array_values( array_filter( explode( '|', reset( $font ) ) ) );
195
            if ( !empty($_thisfont) ) {
196
                $fontsCollection[$i]["fonts"] = $_thisfont;
197
                // And add subset if any
198
                $subset = ( is_array( $font ) ) ? end( $font ) : '';
199
                if ( false !== strpos( $subset, 'subset=' ) ) {
200
                    $subset = explode( 'subset=', $subset );
201
                    $fontsCollection[$i]["subsets"] = explode( ',', $subset[1] );
202
                }
203
            }
204
            // And remove Google Fonts.
205
            $in = str_replace( $matches[0][ $i ], '', $in );
206
        }
207
        $i++;
208
    }
209
210
    $_fontsOut="";
211
    if ( $autoptimize_extra_options['autoptimize_extra_radio_field_4'] == "3" ) {
212
        // aggregate & link
213
        $_fontsString="";
214
        $_subsetString="";
215
        foreach ($fontsCollection as $font) {
216
            $_fontsString .= '|'.trim( implode( '|' , $font["fonts"] ), '|' );
217
            if ( !empty( $font["subsets"] ) ) {
218
                $_subsetString .= implode( ',', $font["subsets"] ); 
219
            }
220
        }
221
                    
222
        if (!empty($_subsetString)) {
223
            $_fontsString = $_fontsString."#038;subset=".$_subsetString;
224
        }
225
226
        $_fontsString = str_replace( '|', '%7C', ltrim($_fontsString,'|') );
227
        
228
        if ( ! empty( $_fontsString ) ) {
229
            $_fontsOut = '<link rel="stylesheet" id="ao_optimized_gfonts" href="https://fonts.googleapis.com/css?family=' . $_fontsString . '" />';
230
        }
231
    } else if ( $autoptimize_extra_options['autoptimize_extra_radio_field_4'] == "4" ) {
232
        // aggregate & load async (webfont.js impl.)
233
        $_fontsArray = array();
234
        foreach ($fontsCollection as $_fonts) {
235
            if ( !empty( $_fonts["subsets"] ) ) {
236
                $_subset = implode(",",$_fonts["subsets"]);
237
                foreach ($_fonts["fonts"] as $key => $_one_font) {
238
                    $_one_font = $_one_font.":".$_subset;
239
                    $_fonts["fonts"][$key] = $_one_font;
240
                } 
241
            }
242
            $_fontsArray = array_merge($_fontsArray, $_fonts["fonts"]);
243
        }
244
        
245
        $_fontsOut = '<script data-cfasync="false" type="text/javascript">WebFontConfig={google:{families:[\'';
246
        foreach ($_fontsArray as $_font) {
247
            $_fontsOut .= $_font."','";
248
        }
249
        $_fontsOut = trim(trim($_fontsOut,"'"),",");
250
        $_fontsOut .= '] },classes:false, events:false, timeout:1500};(function() {var wf = document.createElement(\'script\');wf.src=\'https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js\';wf.type=\'text/javascript\';wf.async=\'true\';var s=document.getElementsByTagName(\'script\')[0];s.parentNode.insertBefore(wf, s);})();</script>';
251
    }
252
 
253
    // inject in HTML
254
    $out = substr_replace($in, $_fontsOut."<link", strpos($in, "<link"), strlen("<link"));
255
    return $out;
256
}
257
258
function autoptimize_extra_preconnectgooglefonts($in) {
259
    $autoptimize_extra_options = autoptimize_extra_get_options();
260
261
    // preconnect to fonts.gstatic.com speed up download of static font-files
262
    $in[] = "https://fonts.gstatic.com";
263
    if ( $autoptimize_extra_options['autoptimize_extra_radio_field_4'] == "4" ) {
264
        // and more preconnects for webfont.js
265
        $in[] = "https://ajax.googleapis.com/";
266
        $in[] = "https://fonts.googleapis.com";
267
    }
268
    return $in;
269
}
270
271
/* admin page functions */
272
function autoptimize_extra_admin() { 
273
    add_submenu_page( null, 'autoptimize_extra', 'autoptimize_extra', 'manage_options', 'autoptimize_extra', 'autoptimize_extra_options_page' );
274
    register_setting( 'autoptimize_extra_settings', 'autoptimize_extra_settings' );
275
}
276
277
function add_autoptimize_extra_tab($in) {
278
    $in=array_merge($in,array('autoptimize_extra' => __('Extra','autoptimize')));
279
    return $in;
280
}
281
282
function autoptimize_extra_options_page() { 
283
    $autoptimize_extra_options = autoptimize_extra_get_options();
284
    $_googlef = $autoptimize_extra_options['autoptimize_extra_radio_field_4'];
285
    ?>
286
    <style>
287
        #ao_settings_form {background: white;border: 1px solid #ccc;padding: 1px 15px;margin: 15px 10px 10px 0;}
288
        #ao_settings_form .form-table th {font-weight: 100;}
289
        #autoptimize_extra_descr{font-size: 120%;}
290
    </style>
291
    <div class="wrap">
292
    <h1><?php _e('Autoptimize Settings','autoptimize'); ?></h1>
293
    <?php echo autoptimizeConfig::ao_admin_tabs(); ?>
294
    <form id='ao_settings_form' action='options.php' method='post'>
295
        <?php settings_fields('autoptimize_extra_settings'); ?>
296
        <h2><?php _e('Extra Auto-Optimizations','autoptimize'); ?></h2>
297
        <span id='autoptimize_extra_descr'><?php _e('The following settings can improve your site\'s performance even more.','autoptimize'); ?></span>
298
        <table class="form-table">
299
            <tr>
300
                <th scope="row"><?php _e('Remove emojis','autoptimize'); ?></th>
301
                <td>
302
                    <label><input type='checkbox' name='autoptimize_extra_settings[autoptimize_extra_checkbox_field_1]' <?php if (!empty($autoptimize_extra_options['autoptimize_extra_checkbox_field_1']) && 1 == $autoptimize_extra_options['autoptimize_extra_checkbox_field_1']) echo 'checked="checked"'; ?> value='1'><?php _e('Removes WordPress\' core emojis\' inline CSS, inline JavaScript, and an otherwise un-autoptimized JavaScript file.','autoptimize'); ?></label>
303
                </td>
304
            </tr>
305
            <tr>
306
                <th scope="row"><?php _e('Remove query strings from static resources','autoptimize'); ?></th>
307
                <td>
308
                    <label><input type='checkbox' name='autoptimize_extra_settings[autoptimize_extra_checkbox_field_0]' <?php if (!empty( $autoptimize_extra_options['autoptimize_extra_checkbox_field_0']) && 1 == $autoptimize_extra_options['autoptimize_extra_checkbox_field_0']) echo 'checked="checked"'; ?> value='1'><?php _e('Removing query strings (or more specificaly the <code>ver</code> parameter) will not improve load time, but might improve performance scores.','autoptimize'); ?></label>
309
                </td>
310
            </tr>
311
            <tr>
312
                <th scope="row"><?php _e('Google Fonts','autoptimize'); ?></th>
313
                <td>
314
                    <input type="radio" name="autoptimize_extra_settings[autoptimize_extra_radio_field_4]" value="1" <?php if (!in_array($_googlef,array(2,3,4))) {echo "checked"; } ?> ><?php _e('Leave as is','autoptimize'); ?><br/>
315
                    <input type="radio" name="autoptimize_extra_settings[autoptimize_extra_radio_field_4]" value="2" <?php checked(2, $_googlef, true); ?> ><?php _e('Remove Google Fonts','autoptimize'); ?><br/>
316
                    <input type="radio" name="autoptimize_extra_settings[autoptimize_extra_radio_field_4]" value="3" <?php checked(3, $_googlef, true); ?> ><?php _e('Combine and link in head','autoptimize'); ?><br/>
317
                    <input type="radio" name="autoptimize_extra_settings[autoptimize_extra_radio_field_4]" value="4" <?php checked(4, $_googlef, true); ?> ><?php _e('Combine and load fonts asynchronously with <a href="https://github.com/typekit/webfontloader#readme" target="_blank">webfont.js</a>','autoptimize'); ?><br/>
318
                </td>
319
            </tr>
320
            <tr>
321
                <th scope="row"><?php _e('Preconnect to 3rd party domains <em>(advanced users)</em>','autoptimize'); ?></th>
322
                <td>
323
                    <label><input type='text' style='width:80%' name='autoptimize_extra_settings[autoptimize_extra_text_field_2]' value='<?php echo $autoptimize_extra_options['autoptimize_extra_text_field_2']; ?>'><br /><?php _e('Add 3rd party domains you want the browser to <a href="https://www.keycdn.com/support/preconnect/#primary" target="_blank">preconnect</a> to, separated by comma\'s. Make sure to include the correct protocol (HTTP or HTTPS).','autoptimize'); ?></label>
324
                </td>
325
            </tr>
326
            <tr>
327
                <th scope="row"><?php _e('Async Javascript-files <em>(advanced users)</em>','autoptimize'); ?></th>
328
                <td>
329
                    <input type='text' style='width:80%' name='autoptimize_extra_settings[autoptimize_extra_text_field_3]' value='<?php echo $autoptimize_extra_options['autoptimize_extra_text_field_3']; ?>'>
330
                    <br />
331
                    <?php _e('Comma-separated list of local or 3rd party JS-files that should loaded with the <code>async</code> flag. JS-files from your own site will be automatically excluded if added here.','autoptimize'); ?>
332
                </td>
333
            </tr>
334
        </table>
335
        <p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="Save Changes"  /></p>
336
    </form>
337
    <?php
338
}
339