Completed
Push — master ( 888448...89a848 )
by frank
07:21 queued 03:15
created

autoptimizeExtra::query_img_provider_stats()   B

Complexity

Conditions 7
Paths 9

Size

Total Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 9
nop 0
dl 0
loc 27
rs 8.5546
c 0
b 0
f 0
1
<?php
2
/**
3
 * Handles autoptimizeExtra frontend features + admin options page
4
 */
5
6
if ( ! defined( 'ABSPATH' ) ) {
7
    exit;
8
}
9
10
class autoptimizeExtra
11
{
12
    /**
13
     * Options
14
     *
15
     * @var array
16
     */
17
    protected $options = array();
18
19
    /**
20
     * Creates an instance and calls run().
21
     *
22
     * @param array $options Optional. Allows overriding options without having to specify them via admin options page.
23
     */
24
    public function __construct( $options = array() )
25
    {
26
        if ( empty( $options ) ) {
27
            $options = self::fetch_options();
28
        }
29
30
        $this->options = $options;
31
    }
32
33 View Code Duplication
    public function run()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
34
    {
35
        if ( is_admin() ) {
36
            add_action( 'admin_menu', array( $this, 'admin_menu' ) );
37
            add_filter( 'autoptimize_filter_settingsscreen_tabs', array( $this, 'add_extra_tab' ) );
38
        } else {
39
            $this->run_on_frontend();
40
        }
41
    }
42
43
    public static function fetch_options()
44
    {
45
        $value = get_option( 'autoptimize_extra_settings' );
46
        if ( empty( $value ) ) {
47
            // Fallback to returning defaults when no stored option exists yet.
48
            $value = autoptimizeConfig::get_ao_extra_default_options();
49
        }
50
51
        return $value;
52
    }
53
54
    public function disable_emojis()
55
    {
56
        // Removing all actions related to emojis!
57
        remove_action( 'admin_print_styles', 'print_emoji_styles' );
58
        remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
59
        remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
60
        remove_action( 'wp_print_styles', 'print_emoji_styles' );
61
        remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
62
        remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
63
        remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
64
65
        // Removes TinyMCE emojis.
66
        add_filter( 'tiny_mce_plugins', array( $this, 'filter_disable_emojis_tinymce' ) );
67
68
        // Removes emoji dns-preftech.
69
        add_filter( 'wp_resource_hints', array( $this, 'filter_remove_emoji_dns_prefetch' ), 10, 2 );
70
    }
71
72
    public function filter_disable_emojis_tinymce( $plugins )
73
    {
74
        if ( is_array( $plugins ) ) {
75
            return array_diff( $plugins, array( 'wpemoji' ) );
76
        } else {
77
            return array();
78
        }
79
    }
80
81
    public function filter_remove_qs( $src )
82
    {
83
        if ( strpos( $src, '?ver=' ) ) {
84
            $src = remove_query_arg( 'ver', $src );
85
        }
86
87
        return $src;
88
    }
89
90
    public function extra_async_js( $in )
91
    {
92
        $exclusions = array();
93 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...
94
            $exclusions = array_fill_keys( array_filter( array_map( 'trim', explode( ',', $in ) ) ), '' );
95
        }
96
97
        $settings = $this->options['autoptimize_extra_text_field_3'];
98
        $async    = array_fill_keys( array_filter( array_map( 'trim', explode( ',', $settings ) ) ), '' );
99
        $attr     = apply_filters( 'autoptimize_filter_extra_async', 'async' );
100
        foreach ( $async as $k => $v ) {
101
            $async[ $k ] = $attr;
102
        }
103
104
        // Merge exclusions & asyncs in one array and return to AO API.
105
        $merged = array_merge( $exclusions, $async );
106
107
        return $merged;
108
    }
109
110
    protected function run_on_frontend()
111
    {
112
        $options = $this->options;
113
114
        // Disable emojis if specified.
115
        if ( ! empty( $options['autoptimize_extra_checkbox_field_1'] ) ) {
116
            $this->disable_emojis();
117
        }
118
119
        // Remove version query parameters.
120
        if ( ! empty( $options['autoptimize_extra_checkbox_field_0'] ) ) {
121
            add_filter( 'script_loader_src', array( $this, 'filter_remove_qs' ), 15, 1 );
122
            add_filter( 'style_loader_src', array( $this, 'filter_remove_qs' ), 15, 1 );
123
        }
124
125
        // Avoiding conflicts of interest when async-javascript plugin is active!
126
        $async_js_plugin_active = autoptimizeUtils::is_plugin_active( 'async-javascript/async-javascript.php' );
127
        if ( ! empty( $options['autoptimize_extra_text_field_3'] ) && ! $async_js_plugin_active ) {
128
            add_filter( 'autoptimize_filter_js_exclude', array( $this, 'extra_async_js' ), 10, 1 );
129
        }
130
131
        // Optimize google fonts!
132
        if ( ! empty( $options['autoptimize_extra_radio_field_4'] ) && ( '1' !== $options['autoptimize_extra_radio_field_4'] ) ) {
133
            add_filter( 'wp_resource_hints', array( $this, 'filter_remove_gfonts_dnsprefetch' ), 10, 2 );
134
            add_filter( 'autoptimize_html_after_minify', array( $this, 'filter_optimize_google_fonts' ), 10, 1 );
135
            add_filter( 'autoptimize_extra_filter_tobepreconn', array( $this, 'filter_preconnect_google_fonts' ), 10, 1 );
136
        }
137
138
        // Preconnect!
139
        if ( ! empty( $options['autoptimize_extra_text_field_2'] ) || has_filter( 'autoptimize_extra_filter_tobepreconn' ) ) {
140
            add_filter( 'wp_resource_hints', array( $this, 'filter_preconnect' ), 10, 2 );
141
        }
142
    }
143
144
    public function filter_remove_emoji_dns_prefetch( $urls, $relation_type )
145
    {
146
        $emoji_svg_url = apply_filters( 'emoji_svg_url', 'https://s.w.org/images/core/emoji/' );
147
148
        return $this->filter_remove_dns_prefetch( $urls, $relation_type, $emoji_svg_url );
149
    }
150
151
    public function filter_remove_gfonts_dnsprefetch( $urls, $relation_type )
152
    {
153
        return $this->filter_remove_dns_prefetch( $urls, $relation_type, 'fonts.googleapis.com' );
154
    }
155
156
    public function filter_remove_dns_prefetch( $urls, $relation_type, $url_to_remove )
157
    {
158
        if ( 'dns-prefetch' === $relation_type ) {
159
            $cnt = 0;
160
            foreach ( $urls as $url ) {
161
                if ( false !== strpos( $url, $url_to_remove ) ) {
162
                    unset( $urls[ $cnt ] );
163
                }
164
                $cnt++;
165
            }
166
        }
167
168
        return $urls;
169
    }
170
171
    public function filter_optimize_google_fonts( $in )
172
    {
173
        // Extract fonts, partly based on wp rocket's extraction code.
174
        $markup = preg_replace( '/<!--(.*)-->/Uis', '', $in );
175
        preg_match_all( '#<link(?:\s+(?:(?!href\s*=\s*)[^>])+)?(?:\s+href\s*=\s*([\'"])((?:https?:)?\/\/fonts\.googleapis\.com\/css(?:(?!\1).)+)\1)(?:\s+[^>]*)?>#iU', $markup, $matches );
176
177
        $fonts_collection = array();
178
        if ( ! $matches[2] ) {
179
            return $in;
180
        }
181
182
        // Store them in $fonts array.
183
        $i = 0;
184
        foreach ( $matches[2] as $font ) {
185
            if ( ! preg_match( '/rel=["\']dns-prefetch["\']/', $matches[0][ $i ] ) ) {
186
                // Get fonts name.
187
                $font = str_replace( array( '%7C', '%7c' ), '|', $font );
188
                $font = explode( 'family=', $font );
189
                $font = ( isset( $font[1] ) ) ? explode( '&', $font[1] ) : array();
190
                // Add font to $fonts[$i] but make sure not to pollute with an empty family!
191
                $_thisfont = array_values( array_filter( explode( '|', reset( $font ) ) ) );
192
                if ( ! empty( $_thisfont ) ) {
193
                    $fonts_collection[ $i ]['fonts'] = $_thisfont;
194
                    // And add subset if any!
195
                    $subset = ( is_array( $font ) ) ? end( $font ) : '';
196
                    if ( false !== strpos( $subset, 'subset=' ) ) {
197
                        $subset                            = str_replace( array( '%2C', '%2c' ), ',', $subset );
198
                        $subset                            = explode( 'subset=', $subset );
199
                        $fonts_collection[ $i ]['subsets'] = explode( ',', $subset[1] );
200
                    }
201
                }
202
                // And remove Google Fonts.
203
                $in = str_replace( $matches[0][ $i ], '', $in );
204
            }
205
            $i++;
206
        }
207
208
        $options      = $this->options;
209
        $fonts_markup = '';
210
        if ( '2' === $options['autoptimize_extra_radio_field_4'] ) {
211
            // Remove Google Fonts.
212
            unset( $fonts_collection );
213
            return $in;
214
        } elseif ( '3' === $options['autoptimize_extra_radio_field_4'] || '5' === $options['autoptimize_extra_radio_field_4'] ) {
215
            // Aggregate & link!
216
            $fonts_string  = '';
217
            $subset_string = '';
218
            foreach ( $fonts_collection as $font ) {
219
                $fonts_string .= '|' . trim( implode( '|', $font['fonts'] ), '|' );
220
                if ( ! empty( $font['subsets'] ) ) {
221
                    $subset_string .= ',' . trim( implode( ',', $font['subsets'] ), ',' );
222
                }
223
            }
224
225
            if ( ! empty( $subset_string ) ) {
226
                $subset_string = str_replace( ',', '%2C', ltrim( $subset_string, ',' ) );
227
                $fonts_string  = $fonts_string . '&#038;subset=' . $subset_string;
228
            }
229
230
            $fonts_string = str_replace( '|', '%7C', ltrim( $fonts_string, '|' ) );
231
232
            if ( ! empty( $fonts_string ) ) {
233
                if ( '5' === $options['autoptimize_extra_radio_field_4'] ) {
234
                    $rel_string = 'rel="preload" as="style" onload="' . autoptimizeConfig::get_ao_css_preload_onload() . '"';
235
                } else {
236
                    $rel_string = 'rel="stylesheet"';
237
                }
238
                $fonts_markup = '<link ' . $rel_string . ' id="ao_optimized_gfonts" href="https://fonts.googleapis.com/css?family=' . $fonts_string . '" />';
239
            }
240
        } elseif ( '4' === $options['autoptimize_extra_radio_field_4'] ) {
241
            // Aggregate & load async (webfont.js impl.)!
242
            $fonts_array = array();
243
            foreach ( $fonts_collection as $_fonts ) {
244
                if ( ! empty( $_fonts['subsets'] ) ) {
245
                    $_subset = implode( ',', $_fonts['subsets'] );
246
                    foreach ( $_fonts['fonts'] as $key => $_one_font ) {
247
                        $_one_font               = $_one_font . ':' . $_subset;
248
                        $_fonts['fonts'][ $key ] = $_one_font;
249
                    }
250
                }
251
                $fonts_array = array_merge( $fonts_array, $_fonts['fonts'] );
252
            }
253
254
            $fonts_array          = array_map( 'urldecode', $fonts_array );
255
            $fonts_markup         = '<script data-cfasync="false" id="ao_optimized_gfonts_config" type="text/javascript">WebFontConfig={google:{families:' . wp_json_encode( $fonts_array ) . ' },classes:false, events:false, timeout:1500};</script>';
256
            $fonts_library_markup = '<script data-cfasync="false" id="ao_optimized_gfonts_webfontloader" type="text/javascript">(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>';
257
            $in                   = substr_replace( $in, $fonts_library_markup . '</head>', strpos( $in, '</head>' ), strlen( '</head>' ) );
258
        }
259
260
        // Replace back in markup.
261
        $inject_point = apply_filters( 'autoptimize_filter_extra_gfont_injectpoint', '<link' );
262
        $out          = substr_replace( $in, $fonts_markup . $inject_point, strpos( $in, $inject_point ), strlen( $inject_point ) );
263
        unset( $fonts_collection );
264
265
        // and insert preload polyfill if "link preload" and if the polyfill isn't there yet (courtesy of inline&defer).
266
        $preload_polyfill = autoptimizeConfig::get_ao_css_preload_polyfill();
267
        if ( '5' === $options['autoptimize_extra_radio_field_4'] && strpos( $out, $preload_polyfill ) === false ) {
268
            $out = str_replace( '</body>', $preload_polyfill . '</body>', $out );
269
        }
270
        return $out;
271
    }
272
273
    public function filter_preconnect( $hints, $relation_type )
274
    {
275
        $options = $this->options;
276
277
        // Get settings and store in array.
278
        $preconns = array_filter( array_map( 'trim', explode( ',', $options['autoptimize_extra_text_field_2'] ) ) );
279
        $preconns = apply_filters( 'autoptimize_extra_filter_tobepreconn', $preconns );
280
281
        // Walk array, extract domain and add to new array with crossorigin attribute.
282
        foreach ( $preconns as $preconn ) {
283
            $parsed = parse_url( $preconn );
284
            if ( is_array( $parsed ) && empty( $parsed['scheme'] ) ) {
285
                $domain = '//' . $parsed['host'];
286
            } elseif ( is_array( $parsed ) ) {
287
                $domain = $parsed['scheme'] . '://' . $parsed['host'];
288
            }
289
290
            if ( ! empty( $domain ) ) {
291
                $hint = array( 'href' => $domain );
292
                // Fonts don't get preconnected unless crossorigin flag is set, non-fonts don't get preconnected if origin flag is set
293
                // so hardcode fonts.gstatic.com to come with crossorigin and have filter to add other domains if needed.
294
                $crossorigins = apply_filters( 'autoptimize_extra_filter_preconn_crossorigin', array( 'https://fonts.gstatic.com' ) );
295
                if ( in_array( $domain, $crossorigins ) ) {
296
                    $hint['crossorigin'] = 'anonymous';
297
                }
298
                $new_hints[] = $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...
299
            }
300
        }
301
302
        // Merge in WP's preconnect hints.
303
        if ( 'preconnect' === $relation_type && ! empty( $new_hints ) ) {
304
            $hints = array_merge( $hints, $new_hints );
305
        }
306
307
        return $hints;
308
    }
309
310
    public function filter_preconnect_google_fonts( $in )
311
    {
312
        if ( '2' !== $this->options['autoptimize_extra_radio_field_4'] ) {
313
            // Preconnect to fonts.gstatic.com unless we remove gfonts.
314
            $in[] = 'https://fonts.gstatic.com';
315
        }
316
317
        if ( '4' === $this->options['autoptimize_extra_radio_field_4'] ) {
318
            // Preconnect even more hosts for webfont.js!
319
            $in[] = 'https://ajax.googleapis.com';
320
            $in[] = 'https://fonts.googleapis.com';
321
        }
322
323
        return $in;
324
    }
325
326
    public function admin_menu()
327
    {
328
        add_submenu_page(
329
            null,
330
            'autoptimize_extra',
331
            'autoptimize_extra',
332
            'manage_options',
333
            'autoptimize_extra',
334
            array( $this, 'options_page' )
335
        );
336
        register_setting( 'autoptimize_extra_settings', 'autoptimize_extra_settings' );
337
    }
338
339
    public function add_extra_tab( $in )
340
    {
341
        $in = array_merge( $in, array( 'autoptimize_extra' => __( 'Extra', 'autoptimize' ) ) );
342
343
        return $in;
344
    }
345
346
    public function options_page()
347
    {
348
        // Working with actual option values from the database here.
349
        // That way any saves are still processed as expected, but we can still
350
        // override behavior by using `new autoptimizeExtra($custom_options)` and not have that custom
351
        // behavior being persisted in the DB even if save is done here.
352
        $options = $this->fetch_options();
353
        $gfonts  = $options['autoptimize_extra_radio_field_4'];
354
        ?>
355
    <style>
356
        #ao_settings_form {background: white;border: 1px solid #ccc;padding: 1px 15px;margin: 15px 10px 10px 0;}
357
        #ao_settings_form .form-table th {font-weight: normal;}
358
        #autoptimize_extra_descr{font-size: 120%;}
359
    </style>
360
    <div class="wrap">
361
    <h1><?php _e( 'Autoptimize Settings', 'autoptimize' ); ?></h1>
362
        <?php echo autoptimizeConfig::ao_admin_tabs(); ?>
363
        <?php if ( 'on' !== get_option( 'autoptimize_js' ) && 'on' !== get_option( 'autoptimize_css' ) && 'on' !== get_option( 'autoptimize_html' ) && ! autoptimizeImages::imgopt_active() ) { ?>
0 ignored issues
show
Bug Best Practice introduced by
The expression \autoptimizeImages::imgopt_active() of type null|boolean is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
364
            <div class="notice-warning notice"><p>
365
            <?php _e( 'Most of below Extra optimizations require at least one of HTML, JS, CSS or Image autoptimizations being active.', 'autoptimize' ); ?>
366
            </p></div>
367
        <?php } ?>
368
369
    <form id='ao_settings_form' action='options.php' method='post'>
370
        <?php settings_fields( 'autoptimize_extra_settings' ); ?>
371
        <h2><?php _e( 'Extra Auto-Optimizations', 'autoptimize' ); ?></h2>
372
        <span id='autoptimize_extra_descr'><?php _e( 'The following settings can improve your site\'s performance even more.', 'autoptimize' ); ?></span>
373
        <table class="form-table">
374
            <tr>
375
                <th scope="row"><?php _e( 'Google Fonts', 'autoptimize' ); ?></th>
376
                <td>
377
                    <input type="radio" name="autoptimize_extra_settings[autoptimize_extra_radio_field_4]" value="1" <?php if ( ! in_array( $gfonts, array( 2, 3, 4, 5 ) ) ) { echo 'checked'; } ?> ><?php _e( 'Leave as is', 'autoptimize' ); ?><br/>
378
                    <input type="radio" name="autoptimize_extra_settings[autoptimize_extra_radio_field_4]" value="2" <?php checked( 2, $gfonts, true ); ?> ><?php _e( 'Remove Google Fonts', 'autoptimize' ); ?><br/>
379
                    <input type="radio" name="autoptimize_extra_settings[autoptimize_extra_radio_field_4]" value="3" <?php checked( 3, $gfonts, true ); ?> ><?php _e( 'Combine and link in head (fonts load fast but are render-blocking)', 'autoptimize' ); ?><br/>
380
                    <input type="radio" name="autoptimize_extra_settings[autoptimize_extra_radio_field_4]" value="5" <?php checked( 5, $gfonts, true ); ?> ><?php _e( 'Combine and preload in head (fonts load late, but are not render-blocking)', 'autoptimize' ); ?><br/>
381
                    <input type="radio" name="autoptimize_extra_settings[autoptimize_extra_radio_field_4]" value="4" <?php checked( 4, $gfonts, true ); ?> ><?php _e( 'Combine and load fonts asynchronously with <a href="https://github.com/typekit/webfontloader#readme" target="_blank">webfont.js</a>', 'autoptimize' ); ?><br/>
382
                </td>
383
            </tr>
384
            <tr>
385
                <th scope="row"><?php _e( 'Remove emojis', 'autoptimize' ); ?></th>
386
                <td>
387
                    <label><input type='checkbox' name='autoptimize_extra_settings[autoptimize_extra_checkbox_field_1]' <?php if ( ! empty( $options['autoptimize_extra_checkbox_field_1'] ) && '1' === $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>
388
                </td>
389
            </tr>
390
            <tr>
391
                <th scope="row"><?php _e( 'Remove query strings from static resources', 'autoptimize' ); ?></th>
392
                <td>
393
                    <label><input type='checkbox' name='autoptimize_extra_settings[autoptimize_extra_checkbox_field_0]' <?php if ( ! empty( $options['autoptimize_extra_checkbox_field_0'] ) && '1' === $options['autoptimize_extra_checkbox_field_0'] ) { echo 'checked="checked"'; } ?> value='1'><?php _e( 'Removing query strings (or more specifically the <code>ver</code> parameter) will not improve load time, but might improve performance scores.', 'autoptimize' ); ?></label>
394
                </td>
395
            </tr>
396
            <tr>
397
                <th scope="row"><?php _e( 'Preconnect to 3rd party domains <em>(advanced users)</em>', 'autoptimize' ); ?></th>
398
                <td>
399
                    <label><input type='text' style='width:80%' name='autoptimize_extra_settings[autoptimize_extra_text_field_2]' value='<?php if ( array_key_exists( 'autoptimize_extra_text_field_2', $options ) ) { echo esc_attr( $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>
400
                </td>
401
            </tr>
402
            <tr>
403
                <th scope="row"><?php _e( 'Async Javascript-files <em>(advanced users)</em>', 'autoptimize' ); ?></th>
404
                <td>
405
                    <?php
406
                    if ( autoptimizeUtils::is_plugin_active( 'async-javascript/async-javascript.php' ) ) {
407
                        // translators: link points Async Javascript settings page.
408
                        printf( __( 'You have "Async JavaScript" installed, %1$sconfiguration of async javascript is best done there%2$s.', 'autoptimize' ), '<a href="' . 'options-general.php?page=async-javascript' . '">', '</a>' );
409
                    } else {
410
                    ?>
411
                        <input type='text' style='width:80%' name='autoptimize_extra_settings[autoptimize_extra_text_field_3]' value='<?php if ( array_key_exists( 'autoptimize_extra_text_field_3', $options ) ) { echo esc_attr( $options['autoptimize_extra_text_field_3'] ); } ?>'>
412
                        <br />
413
                        <?php
414
                            _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' );
415
                            // translators: %s will be replaced by a link to the "async javascript" plugin.
416
                            echo sprintf( __( 'Configuration of async javascript is easier and more flexible using the %s plugin.', 'autoptimize' ), '"<a href="https://wordpress.org/plugins/async-javascript" target="_blank">Async Javascript</a>"' );
417
                            $asj_install_url = network_admin_url() . 'plugin-install.php?s=async+javascript&tab=search&type=term';
418
                            echo sprintf( ' <a href="' . $asj_install_url . '">%s</a>', __( 'Click here to install and activate it.', 'autoptimize' ) );
419
                    }
420
                    ?>
421
                </td>
422
            </tr>
423
            <tr>
424
                <th scope="row"><?php _e( 'Optimize YouTube videos', 'autoptimize' ); ?></th>
425
                <td>
426
                    <?php
427
                    if ( autoptimizeUtils::is_plugin_active( 'wp-youtube-lyte/wp-youtube-lyte.php' ) ) {
428
                        _e( 'Great, you have WP YouTube Lyte installed.', 'autoptimize' );
429
                        $lyte_config_url = 'options-general.php?page=lyte_settings_page';
430
                        echo sprintf( ' <a href="' . $lyte_config_url . '">%s</a>', __( 'Click here to configure it.', 'autoptimize' ) );
431 View Code Duplication
                    } else {
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...
432
                        // translators: %s will be replaced by a link to "wp youtube lyte" plugin.
433
                        echo sprintf( __( '%s allows you to “lazy load” your videos, by inserting responsive “Lite YouTube Embeds". ', 'autoptimize' ), '<a href="https://wordpress.org/plugins/wp-youtube-lyte" target="_blank">WP YouTube Lyte</a>' );
434
                        $lyte_install_url = network_admin_url() . 'plugin-install.php?s=lyte&tab=search&type=term';
435
                        echo sprintf( ' <a href="' . $lyte_install_url . '">%s</a>', __( 'Click here to install and activate it.', 'autoptimize' ) );
436
                    }
437
                    ?>
438
                </td>
439
            </tr>
440
        </table>
441
        <p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="<?php _e( 'Save Changes', 'autoptimize' ); ?>" /></p>
442
    </form>
443
        <?php
444
    }
445
}
446