Completed
Push — master ( b4100c...ed2097 )
by frank
01:49
created

autoptimizeCriticalCSSCore::ao_ccss_frontend()   F

Complexity

Conditions 40
Paths 28

Size

Total Lines 103

Duplication

Lines 20
Ratio 19.42 %

Importance

Changes 0
Metric Value
cc 40
nc 28
nop 1
dl 20
loc 103
rs 3.3333
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Critical CSS Core logic:
4
 * gets called by AO core, checks the rules and if a matching rule is found returns the associated CCSS.
5
 */
6
7
if ( ! defined( 'ABSPATH' ) ) {
8
    exit;
9
}
10
11
class autoptimizeCriticalCSSCore {
12 View Code Duplication
    public function __construct()
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...
13
    {
14
        // fetch all options at once and populate them individually explicitely as globals.
15
        $all_options = autoptimizeCriticalCSSBase::fetch_options();
16
        foreach ( $all_options as $_option => $_value ) {
17
            global ${$_option};
18
            ${$_option} = $_value;
19
        }
20
21
        $this->run();
22
    }
23
24
    public function run() {
25
        global $ao_css_defer;
26
        global $ao_ccss_deferjquery;
27
        global $ao_ccss_key;
28
29
        // add all filters to do CCSS if key present.
30
        if ( $ao_css_defer && isset( $ao_ccss_key ) && ! empty( $ao_ccss_key ) ) {
31
            // Set AO behavior: disable minification to avoid double minifying and caching.
32
            add_filter( 'autoptimize_filter_css_critcss_minify', '__return_false' );
33
            add_filter( 'autoptimize_filter_css_defer_inline', array( $this, 'ao_ccss_frontend' ), 10, 1 );
34
35
            // Add the action to enqueue jobs for CriticalCSS cron.
36
            add_action( 'autoptimize_action_css_hash', array( 'autoptimizeCriticalCSSEnqueue', 'ao_ccss_enqueue' ), 10, 1 );
37
38
            // conditionally add the filter to defer jquery and others.
39
            if ( $ao_ccss_deferjquery ) {
40
                add_filter( 'autoptimize_html_after_minify', array( $this, 'ao_ccss_defer_jquery' ), 11, 1 );
41
            }
42
43
            // Order paths by length, as longest ones have greater priority in the rules.
44
            if ( ! empty( $ao_ccss_rules['paths'] ) ) {
0 ignored issues
show
Bug introduced by
The variable $ao_ccss_rules seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
45
                $keys = array_map( 'strlen', array_keys( $ao_ccss_rules['paths'] ) );
46
                array_multisort( $keys, SORT_DESC, $ao_ccss_rules['paths'] );
47
            }
48
49
            // Add an array with default WordPress's conditional tags
50
            // NOTE: these tags are sorted.
51
            global $ao_ccss_types;
52
            $ao_ccss_types = $this->get_ao_ccss_core_types();
53
54
            // Extend conditional tags on plugin initalization.
55
            add_action( apply_filters( 'autoptimize_filter_ccss_extend_types_hook', 'init' ), array( $this, 'ao_ccss_extend_types' ) );
56
        }
57
    }
58
59
    public function ao_ccss_frontend( $inlined ) {
60
        // Apply CriticalCSS to frontend pages
61
        // Attach types and settings arrays.
62
        global $ao_ccss_types;
63
        global $ao_ccss_rules;
64
        global $ao_ccss_additional;
65
        global $ao_ccss_loggedin;
66
        global $ao_ccss_debug;
67
        global $ao_ccss_keyst;
68
        $no_ccss = '';
69
70
        // Only if keystatus is OK and option to add CCSS for logged on users is on or user is not logged in.
71
        if ( ( $ao_ccss_keyst && 2 == $ao_ccss_keyst ) && ( $ao_ccss_loggedin || ! is_user_logged_in() ) ) {
72
            // Check for a valid CriticalCSS based on path to return its contents.
73
            $req_path = strtok( urldecode( $_SERVER['REQUEST_URI'] ), '?' );
74
            if ( ! empty( $ao_ccss_rules['paths'] ) ) {
75
                foreach ( $ao_ccss_rules['paths'] as $path => $rule ) {
76
                    // explicit match OR partial match if MANUAL rule.
77
                    if ( $req_path == $path || ( false == $rule['hash'] && false != $rule['file'] && strpos( $req_path, str_replace( site_url(), '', $path ) ) !== false ) ) {
78
                        if ( file_exists( AO_CCSS_DIR . $rule['file'] ) ) {
79
                            $_ccss_contents = file_get_contents( AO_CCSS_DIR . $rule['file'] );
80
                            if ( 'none' != $_ccss_contents ) {
81
                                if ( $ao_ccss_debug ) {
82
                                    $_ccss_contents = '/* PATH: ' . $path . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
83
                                }
84
                                return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $ao_ccss_additional );
85
                            } else {
86
                                $no_ccss = 'none';
87
                            }
88
                        }
89
                    }
90
                }
91
            }
92
93
            // Check for a valid CriticalCSS based on conditional tags to return its contents.
94
            if ( ! empty( $ao_ccss_rules['types'] ) && 'none' !== $no_ccss ) {
95
                // order types-rules by the order of the original $ao_ccss_types array so as not to depend on the order in which rules were added.
96
                $ao_ccss_rules['types'] = array_replace( array_intersect_key( array_flip( $ao_ccss_types ), $ao_ccss_rules['types'] ), $ao_ccss_rules['types'] );
97
                $is_front_page          = is_front_page();
98
99
                foreach ( $ao_ccss_rules['types'] as $type => $rule ) {
100
                    if ( in_array( $type, $ao_ccss_types ) && file_exists( AO_CCSS_DIR . $rule['file'] ) ) {
101
                        $_ccss_contents = file_get_contents( AO_CCSS_DIR . $rule['file'] );
102
                        if ( $is_front_page && 'is_front_page' == $type ) {
103
                            if ( 'none' != $_ccss_contents ) {
104
                                if ( $ao_ccss_debug ) {
105
                                    $_ccss_contents = '/* TYPES: ' . $type . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
106
                                }
107
                                return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $ao_ccss_additional );
108
                            } else {
109
                                $no_ccss = 'none';
110
                            }
111
                        } elseif ( strpos( $type, 'custom_post_' ) === 0 && ! $is_front_page ) {
112
                            if ( get_post_type( get_the_ID() ) === substr( $type, 12 ) ) {
113
                                if ( 'none' != $_ccss_contents ) {
114
                                    if ( $ao_ccss_debug ) {
115
                                        $_ccss_contents = '/* TYPES: ' . $type . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
116
                                    }
117
                                    return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $ao_ccss_additional );
118
                                } else {
119
                                    $no_ccss = 'none';
120
                                }
121
                            }
122
                        } elseif ( 0 === strpos( $type, 'template_' ) && ! $is_front_page ) {
123 View Code Duplication
                            if ( is_page_template( substr( $type, 9 ) ) ) {
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...
124
                                if ( 'none' != $_ccss_contents ) {
125
                                    if ( $ao_ccss_debug ) {
126
                                        $_ccss_contents = '/* TYPES: ' . $type . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
127
                                    }
128
                                    return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $ao_ccss_additional );
129
                                } else {
130
                                    $no_ccss = 'none';
131
                                }
132
                            }
133
                        } elseif ( ! $is_front_page ) {
134
                            // all "normal" conditional tags, core + woo + buddypress + edd + bbpress
135
                            // but we have to remove the prefix for the non-core ones for them to function.
136
                            $type = str_replace( array( 'woo_', 'bp_', 'bbp_', 'edd_' ), '', $type );
137 View Code Duplication
                            if ( function_exists( $type ) && call_user_func( $type ) ) {
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...
138
                                if ( 'none' != $_ccss_contents ) {
139
                                    if ( $ao_ccss_debug ) {
140
                                        $_ccss_contents = '/* TYPES: ' . $type . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
141
                                    }
142
                                    return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $ao_ccss_additional );
143
                                } else {
144
                                    $no_ccss = 'none';
145
                                }
146
                            }
147
                        }
148
                    }
149
                }
150
            }
151
        }
152
153
        // Finally, inline the default CriticalCSS if any or else the entire CSS for the page
154
        // This also applies to logged in users if the option to add CCSS for logged in users has been disabled.
155
        if ( ! empty( $inlined ) && 'none' !== $no_ccss ) {
156
            return apply_filters( 'autoptimize_filter_ccss_core_ccss', $inlined . $ao_ccss_additional );
157
        } else {
158
            add_filter( 'autoptimize_filter_css_inline', '__return_true' );
159
            return;
160
        }
161
    }
162
163
    public function ao_ccss_defer_jquery( $in ) {
164
        // try to defer all JS (main goal being jquery.js as AO by default does not aggregate that).
165
        if ( ( ! is_user_logged_in() || $ao_ccss_loggedin ) && preg_match_all( '#<script.*>(.*)</script>#Usmi', $in, $matches, PREG_SET_ORDER ) ) {
0 ignored issues
show
Bug introduced by
The variable $ao_ccss_loggedin does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
166
            foreach ( $matches as $match ) {
167
                if ( ( ! preg_match( '/<script.* type\s?=.*>/', $match[0] ) || preg_match( '/type\s*=\s*[\'"]?(?:text|application)\/(?:javascript|ecmascript)[\'"]?/i', $match[0] ) ) && '' !== $match[1] && ( false !== strpos( $match[1], 'jQuery' ) || false !== strpos( $match[1], '$' ) ) ) {
168
                    // inline js that requires jquery, wrap deferring JS around it to defer it.
169
                    $new_match = 'var aoDeferInlineJQuery=function(){' . $match[1] . '}; if (document.readyState === "loading") {document.addEventListener("DOMContentLoaded", aoDeferInlineJQuery);} else {aoDeferInlineJQuery();}';
170
                    $in        = str_replace( $match[1], $new_match, $in );
171
                } elseif ( '' === $match[1] && false !== strpos( $match[0], 'src=' ) && false === strpos( $match[0], 'defer' ) ) {
172
                    // linked non-aggregated JS, defer it.
173
                    $new_match = str_replace( '<script ', '<script defer ', $match[0] );
174
                    $in        = str_replace( $match[0], $new_match, $in );
175
                }
176
            }
177
        }
178
        return $in;
179
    }
180
181
    public function ao_ccss_extend_types() {
182
        // Extend contidional tags
183
        // Attach the conditional tags array.
184
        global $ao_ccss_types;
185
186
        // in some cases $ao_ccss_types is empty and/or not an array, this should work around that problem.
187
        if ( empty( $ao_ccss_types ) || ! is_array( $ao_ccss_types ) ) {
188
            $ao_ccss_types = get_ao_ccss_core_types();
189
            autoptimizeCriticalCSSCore::ao_ccss_log( 'Empty types array in extend, refetching array with core conditionals.', 3 );
190
        }
191
192
        // Custom Post Types.
193
        $cpts = get_post_types(
194
            array(
195
                'public'   => true,
196
                '_builtin' => false,
197
            ),
198
            'names',
199
            'and'
200
        );
201
        foreach ( $cpts as $cpt ) {
202
            array_unshift( $ao_ccss_types, 'custom_post_' . $cpt );
203
        }
204
205
        // Templates.
206
        $templates = wp_get_theme()->get_page_templates();
207
        foreach ( $templates as $tplfile => $tplname ) {
208
            array_unshift( $ao_ccss_types, 'template_' . $tplfile );
209
        }
210
211
        // bbPress tags.
212
        if ( function_exists( 'is_bbpress' ) ) {
213
            $ao_ccss_types = array_merge(
214
                array(
215
                    'bbp_is_bbpress',
216
                    'bbp_is_favorites',
217
                    'bbp_is_forum_archive',
218
                    'bbp_is_replies_created',
219
                    'bbp_is_reply_edit',
220
                    'bbp_is_reply_move',
221
                    'bbp_is_search',
222
                    'bbp_is_search_results',
223
                    'bbp_is_single_forum',
224
                    'bbp_is_single_reply',
225
                    'bbp_is_single_topic',
226
                    'bbp_is_single_user',
227
                    'bbp_is_single_user_edit',
228
                    'bbp_is_single_view',
229
                    'bbp_is_subscriptions',
230
                    'bbp_is_topic_archive',
231
                    'bbp_is_topic_edit',
232
                    'bbp_is_topic_merge',
233
                    'bbp_is_topic_split',
234
                    'bbp_is_topic_tag',
235
                    'bbp_is_topic_tag_edit',
236
                    'bbp_is_topics_created',
237
                    'bbp_is_user_home',
238
                    'bbp_is_user_home_edit',
239
                ), $ao_ccss_types
240
            );
241
        }
242
243
        // BuddyPress tags.
244
        if ( function_exists( 'is_buddypress' ) ) {
245
            $ao_ccss_types = array_merge(
246
                array(
247
                    'bp_is_activation_page',
248
                    'bp_is_activity',
249
                    'bp_is_blogs',
250
                    'bp_is_buddypress',
251
                    'bp_is_change_avatar',
252
                    'bp_is_create_blog',
253
                    'bp_is_friend_requests',
254
                    'bp_is_friends',
255
                    'bp_is_friends_activity',
256
                    'bp_is_friends_screen',
257
                    'bp_is_group_admin_page',
258
                    'bp_is_group_create',
259
                    'bp_is_group_forum',
260
                    'bp_is_group_forum_topic',
261
                    'bp_is_group_home',
262
                    'bp_is_group_invites',
263
                    'bp_is_group_leave',
264
                    'bp_is_group_members',
265
                    'bp_is_group_single',
266
                    'bp_is_groups',
267
                    'bp_is_messages',
268
                    'bp_is_messages_compose_screen',
269
                    'bp_is_messages_conversation',
270
                    'bp_is_messages_inbox',
271
                    'bp_is_messages_sentbox',
272
                    'bp_is_my_activity',
273
                    'bp_is_my_blogs',
274
                    'bp_is_notices',
275
                    'bp_is_profile_edit',
276
                    'bp_is_register_page',
277
                    'bp_is_settings_component',
278
                    'bp_is_user',
279
                    'bp_is_user_profile',
280
                    'bp_is_wire',
281
                ), $ao_ccss_types
282
            );
283
        }
284
285
        // Easy Digital Downloads (EDD) tags.
286
        if ( function_exists( 'edd_is_checkout' ) ) {
287
            $ao_ccss_types = array_merge(
288
                array(
289
                    'edd_is_checkout',
290
                    'edd_is_failed_transaction_page',
291
                    'edd_is_purchase_history_page',
292
                    'edd_is_success_page',
293
                ), $ao_ccss_types
294
            );
295
        }
296
297
        // WooCommerce tags.
298
        if ( class_exists( 'WooCommerce' ) ) {
299
            $ao_ccss_types = array_merge(
300
                array(
301
                    'woo_is_account_page',
302
                    'woo_is_cart',
303
                    'woo_is_checkout',
304
                    'woo_is_product',
305
                    'woo_is_product_category',
306
                    'woo_is_product_tag',
307
                    'woo_is_shop',
308
                    'woo_is_wc_endpoint_url',
309
                    'woo_is_woocommerce',
310
                ), $ao_ccss_types
311
            );
312
        }
313
    }
314
315
    public function get_ao_ccss_core_types() {
316
        global $ao_ccss_types;
317
        if ( empty( $ao_ccss_types ) || ! is_array( $ao_ccss_types ) ) {
318
            return array(
319
                'is_404',
320
                'is_archive',
321
                'is_author',
322
                'is_category',
323
                'is_front_page',
324
                'is_home',
325
                'is_page',
326
                'is_post',
327
                'is_search',
328
                'is_attachment',
329
                'is_single',
330
                'is_sticky',
331
                'is_paged',
332
            );
333
        } else {
334
            return $ao_ccss_types;
335
        }
336
    }
337
338
    public static function ao_ccss_key_status( $render ) {
339
        // Provide key status
340
        // Get key and key status.
341
        global $ao_ccss_key;
342
        global $ao_ccss_keyst;
343
        $self       = new self();
344
        $key        = $ao_ccss_key;
345
        $key_status = $ao_ccss_keyst;
346
347
        // Prepare returned variables.
348
        $key_return = array();
349
        $status     = false;
0 ignored issues
show
Unused Code introduced by
$status is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
350
351
        if ( $key && 2 == $key_status ) {
352
            // Key exists and its status is valid.
353
            // Set valid key status.
354
            $status     = 'valid';
355
            $status_msg = __( 'Valid' );
356
            $color      = '#46b450'; // Green.
357
            $message    = null;
358 View Code Duplication
        } elseif ( $key && 1 == $key_status ) {
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...
359
            // Key exists but its validation has failed.
360
            // Set invalid key status.
361
            $status     = 'invalid';
362
            $status_msg = __( 'Invalid' );
363
            $color      = '#dc3232'; // Red.
364
            $message    = __( 'Your API key is invalid. Please enter a valid <a href="https://criticalcss.com/?aff=1" target="_blank">criticalcss.com</a> key.', 'autoptimize' );
365
        } elseif ( $key && ! $key_status ) {
366
            // Key exists but it has no valid status yet
367
            // Perform key validation.
368
            $key_check = $self->ao_ccss_key_validation( $key );
369
370
            // Key is valid, set valid status.
371
            if ( $key_check ) {
372
                $status     = 'valid';
373
                $status_msg = __( 'Valid' );
374
                $color      = '#46b450'; // Green.
375
                $message    = null;
376
            } else {
377
                // Key is invalid, set invalid status.
378
                $status     = 'invalid';
379
                $status_msg = __( 'Invalid' );
380
                $color      = '#dc3232'; // Red.
381
                if ( get_option( 'autoptimize_ccss_keyst' ) == 1 ) {
382
                    $message = __( 'Your API key is invalid. Please enter a valid <a href="https://criticalcss.com/?aff=1" target="_blank">criticalcss.com</a> key.', 'autoptimize' );
383
                } else {
384
                    $message = __( 'Something went wrong when checking your API key, make sure you server can communicate with https://criticalcss.com and/ or try again later.', 'autoptimize' );
385
                }
386
            }
387 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...
388
            // No key nor status
389
            // Set no key status.
390
            $status     = 'nokey';
391
            $status_msg = __( 'None' );
392
            $color      = '#ffb900'; // Yellow.
393
            $message    = __( 'Please enter a valid <a href="https://criticalcss.com/?aff=1" target="_blank">criticalcss.com</a> API key to start.', 'autoptimize' );
394
        }
395
396
        // Fill returned values.
397
        $key_return['status'] = $status;
398
        // Provide rendering information if required.
399
        if ( $render ) {
400
            $key_return['stmsg'] = $status_msg;
401
            $key_return['color'] = $color;
402
            $key_return['msg']   = $message;
403
        }
404
405
        // Return key status.
406
        return $key_return;
407
    }
408
409
    public function ao_ccss_key_validation( $key ) {
410
        // POST a dummy job to criticalcss.com to check for key validation
411
        // Prepare home URL for the request.
412
        $src_url = get_home_url();
413
        $src_url = apply_filters( 'autoptimize_filter_ccss_cron_srcurl', $src_url );
414
415
        // Prepare the request.
416
        $url  = esc_url_raw( AO_CCSS_API . 'generate' );
417
        $args = array(
418
            'headers' => array(
419
                'User-Agent'    => 'Autoptimize CriticalCSS Power-Up v' . AO_CCSS_VER,
420
                'Content-type'  => 'application/json; charset=utf-8',
421
                'Authorization' => 'JWT ' . $key,
422
                'Connection'    => 'close',
423
            ),
424
            // Body must be JSON.
425
            'body'    => json_encode(
426
                array(
427
                    'url'    => $src_url,
428
                    'aff'    => 1,
429
                    'aocssv' => AO_CCSS_VER,
430
                )
431
            ),
432
        );
433
434
        // Dispatch the request and store its response code.
435
        $req  = wp_safe_remote_post( $url, $args );
436
        $code = wp_remote_retrieve_response_code( $req );
437
        $body = json_decode( wp_remote_retrieve_body( $req ), true );
438
439
        if ( 200 == $code ) {
440
            // Response is OK.
441
            // Set key status as valid and log key check.
442
            update_option( 'autoptimize_ccss_keyst', 2 );
443
            autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: API key is valid, updating key status', 3 );
444
445
            // extract job-id from $body and put it in the queue as a P job
446
            // but only if no jobs and no rules!
447
            global $ao_ccss_queue;
448
            global $ao_ccss_rules;
449
450
            if ( 0 == count( $ao_ccss_queue ) && 0 == count( $ao_ccss_rules['types'] ) && 0 == count( $ao_ccss_rules['paths'] ) ) {
451
                if ( 'JOB_QUEUED' == $body['job']['status'] || 'JOB_ONGOING' == $body['job']['status'] ) {
452
                    $jprops['ljid']     = 'firstrun';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$jprops was never initialized. Although not strictly required by PHP, it is generally a good practice to add $jprops = 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...
453
                    $jprops['rtarget']  = 'types|is_front_page';
454
                    $jprops['ptype']    = 'is_front_page';
455
                    $jprops['hashes'][] = 'dummyhash';
456
                    $jprops['hash']     = 'dummyhash';
457
                    $jprops['file']     = null;
458
                    $jprops['jid']      = $body['job']['id'];
459
                    $jprops['jqstat']   = $body['job']['status'];
460
                    $jprops['jrstat']   = null;
461
                    $jprops['jvstat']   = null;
462
                    $jprops['jctime']   = microtime( true );
463
                    $jprops['jftime']   = null;
464
                    $ao_ccss_queue['/'] = $jprops;
465
                    $ao_ccss_queue_raw  = json_encode( $ao_ccss_queue );
466
                    update_option( 'autoptimize_ccss_queue', $ao_ccss_queue_raw, false );
467
                    autoptimizeCriticalCSSCore::ao_ccss_log( 'Created P job for is_front_page based on API key check response.', 3 );
468
                }
469
            }
470
            return true;
471
        } elseif ( 401 == $code ) {
472
            // Response is unauthorized
473
            // Set key status as invalid and log key check.
474
            update_option( 'autoptimize_ccss_keyst', 1 );
475
            autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: API key is invalid, updating key status', 3 );
476
            return false;
477
        } else {
478
            // Response unkown
479
            // Log key check attempt.
480
            autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: could not check API key status, this is a service error, body follows if any...', 2 );
481
            if ( ! empty( $body ) ) {
482
                autoptimizeCriticalCSSCore::ao_ccss_log( print_r( $body, true ), 2 );
483
            }
484
            if ( is_wp_error( $req ) ) {
485
                autoptimizeCriticalCSSCore::ao_ccss_log( $req->get_error_message(), 2 );
486
            }
487
            return false;
488
        }
489
    }
490
491
    public static function ao_ccss_viewport() {
492
        // Get viewport size
493
        // Attach viewport option.
494
        global $ao_ccss_viewport;
495
496
        // Prepare viewport array.
497
        $viewport = array();
498
499
        // Viewport Width.
500
        if ( ! empty( $ao_ccss_viewport['w'] ) ) {
501
            $viewport['w'] = $ao_ccss_viewport['w'];
502
        } else {
503
            $viewport['w'] = '';
504
        }
505
506
        // Viewport Height.
507
        if ( ! empty( $ao_ccss_viewport['h'] ) ) {
508
            $viewport['h'] = $ao_ccss_viewport['h'];
509
        } else {
510
            $viewport['h'] = '';
511
        }
512
513
        return $viewport;
514
    }
515
516
    public static function ao_ccss_check_contents( $ccss ) {
517
        // Perform basic exploit avoidance and CSS validation.
518
        if ( ! empty( $ccss ) ) {
519
            // Try to avoid code injection.
520
            $blacklist = array( '#!/', 'function(', '<script', '<?php' );
521
            foreach ( $blacklist as $blacklisted ) {
522
                if ( strpos( $ccss, $blacklisted ) !== false ) {
523
                    autoptimizeCriticalCSSCore::ao_ccss_log( 'Critical CSS received contained blacklisted content.', 2 );
524
                    return false;
525
                }
526
            }
527
528
            // Check for most basics CSS structures.
529
            $pinklist = array( '{', '}', ':' );
530
            foreach ( $pinklist as $needed ) {
531
                if ( false === strpos( $ccss, $needed ) && 'none' !== $ccss ) {
532
                    autoptimizeCriticalCSSCore::ao_ccss_log( 'Critical CSS received did not seem to contain real CSS.', 2 );
533
                    return false;
534
                }
535
            }
536
        }
537
538
        // Return true if file critical CSS is sane.
539
        return true;
540
    }
541
542
    public static function ao_ccss_log( $msg, $lvl ) {
543
        // Commom logging facility
544
        // Attach debug option.
545
        global $ao_ccss_debug;
546
547
        // Prepare log levels, where accepted $lvl are:
548
        // 1: II (for info)
549
        // 2: EE (for error)
550
        // 3: DD (for debug)
551
        // Default: UU (for unkown).
552
        $level = false;
553
        switch ( $lvl ) {
554
            case 1:
555
                $level = 'II';
556
                break;
557
            case 2:
558
                $level = 'EE';
559
                break;
560
            case 3:
561
                // Output debug messages only if debug mode is enabled.
562
                if ( $ao_ccss_debug ) {
563
                    $level = 'DD';
564
                }
565
                break;
566
            default:
567
                $level = 'UU';
568
        }
569
570
        // Prepare and write a log message if there's a valid level.
571
        if ( $level ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $level of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
572
573
            // Prepare message.
574
            $message = date( 'c' ) . ' - [' . $level . '] ' . htmlentities( $msg ) . '<br>';
575
576
            // Write message to log file.
577
            error_log( $message, 3, AO_CCSS_LOG );
578
        }
579
    }
580
}
581