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

autoptimizeCriticalCSSCron::ao_ccss_rule_update()   B

Complexity

Conditions 10
Paths 10

Size

Total Lines 54

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
nc 10
nop 4
dl 0
loc 54
rs 7.1369
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 Cron logic:
4
 * processes the queue, submitting jobs to criticalcss.com and retrieving generated CSS from criticalcss.com and saving rules.
5
 */
6
7
if ( ! defined( 'ABSPATH' ) ) {
8
    exit;
9
}
10
11
class autoptimizeCriticalCSSCron {
12
    public function __construct()
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
        // Add queue control to a registered event.
22
        add_action( 'ao_ccss_queue', array( $this, 'ao_ccss_queue_control' ) );
23
        // Add cleaning job to a registered event.
24
        add_action( 'ao_ccss_maintenance', array( $this, 'ao_ccss_cleaning' ) );
25
    }
26
27
    public function ao_ccss_queue_control() {
28
        // The queue execution backend.
29
        global $ao_ccss_key;
30
        if ( ! isset( $ao_ccss_key ) || empty( $ao_ccss_key ) ) {
31
            // no key set, not processing the queue!
32
            autoptimizeCriticalCSSCore::ao_ccss_log( 'No key set, so not processing queue.', 3 );
33
            return;
34
        }
35
36
        /**
37
         * Provide a debug facility for the queue
38
         *    This debug facility provides a way to easily force some queue behaviors useful for development and testing.
39
         *    To enable this feature, create the file AO_CCSS_DIR . 'queue.json' with a JSON object like the one bellow:
40
         *
41
         *    {"enable":bool,"htcode":int,"status":0|"str","resultStatus ":0|"str","validationStatus":0|"str"}
42
         *
43
         *    Where values are:
44
         *    - enable                    : 0 or 1, enable or disable this debug facility straight from the file
45
         *    - htcode                    : 0 or any HTTP reponse code (e.g. 2xx, 4xx, 5xx) to force API responses
46
         *    - status                    : 0 or a valid value for 'status' (see 'Generating critical css - Job Status Types' in spec docs)
47
         *    - resultStatus        : 0 or a valid value for 'resultStatus' (see 'Appendix - Result status types' in the spec docs)
48
         *    - validationStatus: 0 or a valid value for 'validationStatus' (see 'Appendix - Validation status types' in the spec docs)
49
         *
50
         *    When properly set, queue will always finish a job with the declared settings above regardless of the real API responses.
51
         */
52
        $queue_debug = false;
53
        if ( file_exists( AO_CCSS_DEBUG ) ) {
54
            $qdobj_raw = file_get_contents( AO_CCSS_DEBUG );
55
            $qdobj     = json_decode( $qdobj_raw, true );
56
            if ( $qdobj ) {
57
                if ( 1 === $qdobj['enable'] ) {
58
                    $queue_debug = true;
59
                    autoptimizeCriticalCSSCore::ao_ccss_log( 'Queue operating in debug mode with the following settings: <' . $qdobj_raw . '>', 3 );
60
                }
61
            }
62
        }
63
64
        // Set some default values for $qdobj to avoid function call warnings.
65
        if ( ! $queue_debug ) {
66
            $qdobj['htcode'] = false;
0 ignored issues
show
Bug introduced by
The variable $qdobj does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
67
        }
68
69
        // Check if queue is already running.
70
        $queue_lock = false;
71
        if ( file_exists( AO_CCSS_LOCK ) ) {
72
            $queue_lock = true;
73
        }
74
75
        // Proceed with the queue if it's not already running.
76
        if ( ! $queue_lock ) {
77
78
            // Log queue start and create the lock file.
79
            autoptimizeCriticalCSSCore::ao_ccss_log( 'Queue control started', 3 );
80
            if ( touch( AO_CCSS_LOCK ) ) {
81
                autoptimizeCriticalCSSCore::ao_ccss_log( 'Queue control locked', 3 );
82
            }
83
84
            // Attach required variables.
85
            global $ao_ccss_queue;
86
            global $ao_ccss_rlimit;
87
88
            // Initialize job counters.
89
            $jc = 1;
90
            $jr = 1;
91
            $jt = count( $ao_ccss_queue );
92
93
            // Sort queue by ascending job status (e.g. ERROR, JOB_ONGOING, JOB_QUEUED, NEW...).
94
            array_multisort( array_column( $ao_ccss_queue, 'jqstat' ), $ao_ccss_queue ); // @codingStandardsIgnoreLine
0 ignored issues
show
Bug introduced by
array_column($ao_ccss_queue, 'jqstat') cannot be passed to array_multisort() as the parameter $arr expects a reference.
Loading history...
95
96
            // Iterates over the entire queue.
97
            foreach ( $ao_ccss_queue as $path => $jprops ) {
98
                // Prepare flags and target rule.
99
                $update      = false;
100
                $deljob      = false;
101
                $rule_update = false;
102
                $oldccssfile = false;
0 ignored issues
show
Unused Code introduced by
$oldccssfile 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...
103
                $trule       = explode( '|', $jprops['rtarget'] );
104
105
                // Log job count.
106
                autoptimizeCriticalCSSCore::ao_ccss_log( 'Processing job ' . $jc . ' of ' . $jt . ' with id <' . $jprops['ljid'] . '> and status <' . $jprops['jqstat'] . '>', 3 );
107
108
                // Process NEW jobs.
109
                if ( 'NEW' == $jprops['jqstat'] ) {
110
111
                    // Log the new job.
112
                    autoptimizeCriticalCSSCore::ao_ccss_log( 'Found NEW job with local ID <' . $jprops['ljid'] . '>, starting its queue processing', 3 );
113
114
                    // Compare job and rule hashes (if any).
115
                    $hash = $this->ao_ccss_diff_hashes( $jprops['ljid'], $jprops['hash'], $jprops['hashes'], $jprops['rtarget'] );
116
117
                    // If job hash is new or different of a previous one.
118
                    if ( $hash ) {
119
                        // Set job hash.
120
                        $jprops['hash'] = $hash;
121
122
                        // If this is not the first job, wait 15 seconds before process next job due criticalcss.com API limits.
123
                        if ( $jr > 1 ) {
124
                            autoptimizeCriticalCSSCore::ao_ccss_log( 'Waiting 15 seconds due to criticalcss.com API limits', 3 );
125
                            sleep( 15 );
126
                        }
127
128
                        // Dispatch the job generate request and increment request count.
129
                        $apireq = $this->ao_ccss_api_generate( $path, $queue_debug, $qdobj['htcode'] );
130
                        $jr++;
131
132
                        // NOTE: All the following conditions maps to the ones in admin_settings_queue.js.php.
133
                        if ( 'JOB_QUEUED' == $apireq['job']['status'] || 'JOB_ONGOING' == $apireq['job']['status'] ) {
134
                            // SUCCESS: request has a valid result.
135
                            // Update job properties.
136
                            $jprops['jid']    = $apireq['job']['id'];
137
                            $jprops['jqstat'] = $apireq['job']['status'];
138
                            autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> generate request successful, remote id <' . $jprops['jid'] . '>, status now is <' . $jprops['jqstat'] . '>', 3 );
139
                        } elseif ( 'STATUS_JOB_BAD' == $apireq['job']['status'] ) {
140
                            // ERROR: concurrent requests
141
                            // Update job properties.
142
                            $jprops['jid']    = $apireq['job']['id'];
143
                            $jprops['jqstat'] = $apireq['job']['status'];
144
                            $jprops['jrstat'] = $apireq['error'];
145
                            $jprops['jvstat'] = 'NONE';
146
                            $jprops['jftime'] = microtime( true );
147
                            autoptimizeCriticalCSSCore::ao_ccss_log( 'Concurrent requests when processing job id <' . $jprops['ljid'] . '>, job status is now <' . $jprops['jqstat'] . '>', 3 );
148 View Code Duplication
                        } elseif ( 'INVALID_JWT_TOKEN' == $apireq['errorCode'] ) {
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...
149
                            // ERROR: key validation
150
                            // Update job properties.
151
                            $jprops['jqstat'] = $apireq['errorCode'];
152
                            $jprops['jrstat'] = $apireq['error'];
153
                            $jprops['jvstat'] = 'NONE';
154
                            $jprops['jftime'] = microtime( true );
155
                            autoptimizeCriticalCSSCore::ao_ccss_log( 'API key validation error when processing job id <' . $jprops['ljid'] . '>, job status is now <' . $jprops['jqstat'] . '>', 3 );
156
                        } elseif ( empty( $apireq ) ) {
157
                            // ERROR: no response
158
                            // Update job properties.
159
                            $jprops['jqstat'] = 'NO_RESPONSE';
160
                            $jprops['jrstat'] = 'NONE';
161
                            $jprops['jvstat'] = 'NONE';
162
                            $jprops['jftime'] = microtime( true );
163
                            autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> request has no response, status now is <' . $jprops['jqstat'] . '>', 3 );
164
                        } else {
165
                            // UNKNOWN: unhandled generate exception
166
                            // Update job properties.
167
                            $jprops['jqstat'] = 'JOB_UNKNOWN';
168
                            $jprops['jrstat'] = 'NONE';
169
                            $jprops['jvstat'] = 'NONE';
170
                            $jprops['jftime'] = microtime( true );
171
                            autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> generate request has an UNKNOWN condition, status now is <' . $jprops['jqstat'] . '>, check log messages above for more information', 2 );
172
                            autoptimizeCriticalCSSCore::ao_ccss_log( 'Job response was: ' . json_encode( $apireq ), 3 );
173
                        }
174
                    } else {
175
                        // SUCCESS: Job hash is equal to a previous one, so it's done
176
                        // Update job status and finish time.
177
                        $jprops['jqstat'] = 'JOB_DONE';
178
                        $jprops['jftime'] = microtime( true );
179
                        autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> requires no further processing, status now is <' . $jprops['jqstat'] . '>', 3 );
180
                    }
181
182
                    // Set queue update flag.
183
                    $update = true;
184
185
                } elseif ( 'JOB_QUEUED' == $jprops['jqstat'] || 'JOB_ONGOING' == $jprops['jqstat'] ) {
186
                    // Process QUEUED and ONGOING jobs
187
                    // Log the pending job.
188
                    autoptimizeCriticalCSSCore::ao_ccss_log( 'Found PENDING job with local ID <' . $jprops['ljid'] . '>, continuing its queue processing', 3 );
189
190
                    // If this is not the first job, wait 15 seconds before process next job due criticalcss.com API limits.
191
                    if ( $jr > 1 ) {
192
                        autoptimizeCriticalCSSCore::ao_ccss_log( 'Waiting 15 seconds due to criticalcss.com API limits', 3 );
193
                        sleep( 15 );
194
                    }
195
196
                    // Dispatch the job result request and increment request count.
197
                    $apireq = $this->ao_ccss_api_results( $jprops['jid'], $queue_debug, $qdobj['htcode'] );
198
                    $jr++;
199
200
                    // NOTE: All the following condigitons maps to the ones in admin_settings_queue.js.php
201
                    // Replace API response values if queue debugging is enabled and some value is set.
202
                    if ( $queue_debug ) {
203
                        if ( $qdobj['status'] ) {
204
                            $apireq['status'] = $qdobj['status'];
205
                        }
206
                        if ( $qdobj['resultStatus'] ) {
207
                            $apireq['resultStatus'] = $qdobj['resultStatus'];
208
                        }
209
                        if ( $qdobj['validationStatus'] ) {
210
                            $apireq['validationStatus'] = $qdobj['validationStatus'];
211
                        }
212
                    }
213
214
                    if ( 'JOB_QUEUED' == $apireq['status'] || 'JOB_ONGOING' == $apireq['status'] ) {
215
                        // SUCCESS: request has a valid result
216
                        // Process a PENDING job
217
                        // Update job properties.
218
                        $jprops['jqstat'] = $apireq['status'];
219
                        autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . '> unchanged', 3 );
220
                    } elseif ( 'JOB_DONE' == $apireq['status'] ) {
221
                        // Process a DONE job
222
                        // New resultStatus from ccss.com "HTML_404", consider as "GOOD" for now.
223
                        if ( 'HTML_404' == $apireq['resultStatus'] ) {
224
                            $apireq['resultStatus'] = 'GOOD';
225
                        }
226
227
                        if ( 'GOOD' == $apireq['resultStatus'] && 'GOOD' == $apireq['validationStatus'] ) {
228
                            // SUCCESS: GOOD job with GOOD validation
229
                            // Update job properties.
230
                            $jprops['file']   = $this->ao_ccss_save_file( $apireq['css'], $trule, false );
231
                            $jprops['jqstat'] = $apireq['status'];
232
                            $jprops['jrstat'] = $apireq['resultStatus'];
233
                            $jprops['jvstat'] = $apireq['validationStatus'];
234
                            $jprops['jftime'] = microtime( true );
235
                            $rule_update      = true;
236
                            autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . '>, file saved <' . $jprops['file'] . '>', 3 );
237
                        } elseif ( 'GOOD' == $apireq['resultStatus'] && ( 'WARN' == $apireq['validationStatus'] || 'BAD' == $apireq['validationStatus'] || 'SCREENSHOT_WARN_BLANK' == $apireq['validationStatus'] ) ) {
238
                            // SUCCESS: GOOD job with WARN or BAD validation
239
                            // Update job properties.
240
                            $jprops['file']   = $this->ao_ccss_save_file( $apireq['css'], $trule, true );
241
                            $jprops['jqstat'] = $apireq['status'];
242
                            $jprops['jrstat'] = $apireq['resultStatus'];
243
                            $jprops['jvstat'] = $apireq['validationStatus'];
244
                            $jprops['jftime'] = microtime( true );
245
                            $rule_update      = true;
246
                            autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . ', file saved <' . $jprops['file'] . '> but requires REVIEW', 3 );
247
                        } elseif ( 'GOOD' != $apireq['resultStatus'] && ( 'GOOD' != $apireq['validationStatus'] || 'WARN' != $apireq['validationStatus'] || 'BAD' != $apireq['validationStatus'] || 'SCREENSHOT_WARN_BLANK' != $apireq['validationStatus'] ) ) {
248
                            // ERROR: no GOOD, WARN or BAD results
249
                            // Update job properties.
250
                            $jprops['jqstat'] = $apireq['status'];
251
                            $jprops['jrstat'] = $apireq['resultStatus'];
252
                            $jprops['jvstat'] = $apireq['validationStatus'];
253
                            $jprops['jftime'] = microtime( true );
254
                            autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> result request successful but job FAILED, status now is <' . $jprops['jqstat'] . '>', 3 );
255
                            $apireq['css'] = '/* critical css removed for DEBUG logging purposes */';
256
                            autoptimizeCriticalCSSCore::ao_ccss_log( 'Job response was: ' . json_encode( $apireq ), 3 );
257
                        } else {
258
                            // UNKNOWN: unhandled JOB_DONE exception
259
                            // Update job properties.
260
                            $jprops['jqstat'] = 'JOB_UNKNOWN';
261
                            $jprops['jrstat'] = $apireq['resultStatus'];
262
                            $jprops['jvstat'] = $apireq['validationStatus'];
263
                            $jprops['jftime'] = microtime( true );
264
                            autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> result request successful but job is UNKNOWN, status now is <' . $jprops['jqstat'] . '>', 2 );
265
                            $apireq['css'] = '/* critical css removed for DEBUG logging purposes */';
266
                            autoptimizeCriticalCSSCore::ao_ccss_log( 'Job response was: ' . json_encode( $apireq ), 3 );
267
                        }
268
                    } elseif ( 'JOB_FAILED' == $apireq['job']['status'] || 'STATUS_JOB_BAD' == $apireq['job']['status'] ) {
269
                        // ERROR: failed job
270
                        // Update job properties.
271
                        $jprops['jqstat'] = $apireq['job']['status'];
272
                        if ( $apireq['error'] ) {
273
                            $jprops['jrstat'] = $apireq['job']['error'];
274
                        } else {
275
                        }
276
                        $jprops['jvstat'] = 'NONE';
277
                        $jprops['jftime'] = microtime( true );
278
                        autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> result request successful but job FAILED, status now is <' . $jprops['jqstat'] . '>', 3 );
279 View Code Duplication
                    } elseif ( 'This css no longer exists. Please re-generate it.' == $apireq['error'] ) {
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...
280
                        // ERROR: CSS doesn't exist
281
                        // Update job properties.
282
                        $jprops['jqstat'] = 'NO_CSS';
283
                        $jprops['jrstat'] = $apireq['error'];
284
                        $jprops['jvstat'] = 'NONE';
285
                        $jprops['jftime'] = microtime( true );
286
                        autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> result request successful but job FAILED, status now is <' . $jprops['jqstat'] . '>', 3 );
287
                    } elseif ( empty( $apireq ) ) {
288
                        // ERROR: no response
289
                        // Update job properties.
290
                        $jprops['jqstat'] = 'NO_RESPONSE';
291
                        $jprops['jrstat'] = 'NONE';
292
                        $jprops['jvstat'] = 'NONE';
293
                        $jprops['jftime'] = microtime( true );
294
                        autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> request has no response, status now is <' . $jprops['jqstat'] . '>', 3 );
295
                    } else {
296
                        // UNKNOWN: unhandled results exception
297
                        // Update job properties.
298
                        $jprops['jqstat'] = 'JOB_UNKNOWN';
299
                        $jprops['jrstat'] = 'NONE';
300
                        $jprops['jvstat'] = 'NONE';
301
                        $jprops['jftime'] = microtime( true );
302
                        autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> result request has an UNKNOWN condition, status now is <' . $jprops['jqstat'] . '>, check log messages above for more information', 2 );
303
                    }
304
305
                    // Set queue update flag.
306
                    $update = true;
307
                }
308
309
                // Mark DONE jobs for removal.
310
                if ( 'JOB_DONE' == $jprops['jqstat'] ) {
311
                    $update = true;
312
                    $deljob = true;
313
                }
314
315
                // Persist updated queue object.
316
                if ( $update ) {
317
                    if ( ! $deljob ) {
318
                        // Update properties of a NEW or PENDING job...
319
                        $ao_ccss_queue[ $path ] = $jprops;
320
                    } else {
321
                        // ...or remove the DONE job.
322
                        unset( $ao_ccss_queue[ $path ] );
323
                        autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> is DONE and was removed from the queue', 3 );
324
                    }
325
326
                    // Update queue object.
327
                    $ao_ccss_queue_raw = json_encode( $ao_ccss_queue );
328
                    update_option( 'autoptimize_ccss_queue', $ao_ccss_queue_raw, false );
329
                    autoptimizeCriticalCSSCore::ao_ccss_log( 'Queue updated by job id <' . $jprops['ljid'] . '>', 3 );
330
331
                    // Update target rule.
332
                    if ( $rule_update ) {
333
                        $this->ao_ccss_rule_update( $jprops['ljid'], $jprops['rtarget'], $jprops['file'], $jprops['hash'] );
334
                        autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> updated the target rule <' . $jprops['rtarget'] . '>', 3 );
335
                    }
336
                } else {
337
                    // Or log no queue action.
338
                    autoptimizeCriticalCSSCore::ao_ccss_log( 'Nothing to do on this job', 3 );
339
                }
340
341
                // Break the loop if request limit is set and was reached.
342
                if ( $ao_ccss_rlimit && $ao_ccss_rlimit == $jr ) {
343
                    autoptimizeCriticalCSSCore::ao_ccss_log( 'The limit of ' . $ao_ccss_rlimit . ' request(s) to criticalcss.com was reached, queue control must finish now', 3 );
344
                    break;
345
                }
346
347
                // Increment job counter.
348
                $jc++;
349
            }
350
351
            // Remove the lock file and log the queue end.
352
            if ( file_exists( AO_CCSS_LOCK ) ) {
353
                unlink( AO_CCSS_LOCK );
354
                autoptimizeCriticalCSSCore::ao_ccss_log( 'Queue control unlocked', 3 );
355
            }
356
            autoptimizeCriticalCSSCore::ao_ccss_log( 'Queue control finished', 3 );
357
358
            // Log that queue is locked.
359
        } else {
360
            autoptimizeCriticalCSSCore::ao_ccss_log( 'Queue is already running, skipping the attempt to run it again', 3 );
361
        }
362
    }
363
364
    public function ao_ccss_diff_hashes( $ljid, $hash, $hashes, $rule ) {
0 ignored issues
show
Unused Code introduced by
The parameter $hash is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
365
        // Compare job hashes
366
        // STEP 1: update job hashes.
367
        if ( 1 == count( $hashes ) ) {
368
            // Job with a single hash
369
            // Set job hash.
370
            $hash = $hashes[0];
371
            autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $ljid . '> updated with SINGLE hash <' . $hash . '>', 3 );
372
        } else {
373
            // Job with multiple hashes
374
            // Loop through hashes to concatenate them.
375
            $nhash = '';
376
            foreach ( $hashes as $shash ) {
377
                $nhash .= $shash;
378
            }
379
380
            // Set job hash.
381
            $hash = md5( $nhash );
382
            autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $ljid . '> updated with a COMPOSITE hash <' . $hash . '>', 3 );
383
        }
384
385
        // STEP 2: compare job to existing jobs to prevent double submission for same type+hash.
386
        global $ao_ccss_queue;
387
388
        foreach ( $ao_ccss_queue as $queue_item ) {
389
            autoptimizeCriticalCSSCore::ao_ccss_log( 'Comparing <' . $rule . $hash . '> with <' . $queue_item['rtarget'] . $queue_item['hash'] . '>', 3 );
390
            if ( $queue_item['hash'] == $hash && $queue_item['rtarget'] == $rule && in_array( $queue_item['jqstat'], array( 'JOB_QUEUED', 'JOB_ONGOING', 'JOB_DONE' ) ) ) {
391
                autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $ljid . '> matches the already pending job <' . $queue_item['ljid'] . '>', 3 );
392
                return false;
393
            }
394
        }
395
396
        // STEP 3: compare job and existing rule (if any) hashes
397
        // Attach required arrays.
398
        global $ao_ccss_rules;
399
400
        // Prepare rule variables.
401
        $trule = explode( '|', $rule );
402
        $srule = $ao_ccss_rules[ $trule[0] ][ $trule[1] ];
403
404
        // Check if a MANUAL rule exist and return false.
405
        if ( ! empty( $srule ) && ( 0 == $srule['hash'] && 0 != $srule['file'] ) ) {
406
            autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $ljid . '> matches the MANUAL rule <' . $trule[0] . '|' . $trule[1] . '>', 3 );
407
            return false;
408
        } elseif ( ! empty( $srule ) ) {
409
            // Check if an AUTO rule exist.
410
            if ( $hash === $srule['hash'] && is_file( AO_CCSS_DIR . $srule['file'] ) && 0 != filesize( AO_CCSS_DIR . $srule['file'] ) ) {
411
                // Check if job hash matches rule, if the CCSS file exists said file is not empty and return FALSE is so.
412
                autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $ljid . '> with hash <' . $hash . '> MATCH the one in rule <' . $trule[0] . '|' . $trule[1] . '>', 3 );
413
                return false;
414
            } else {
415
                // Or return the new hash if they differ.
416
                autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $ljid . '> with hash <' . $hash . '> DOES NOT MATCH the one in rule <' . $trule[0] . '|' . $trule[1] . '> or rule\'s CCSS file was invalid.', 3 );
417
                return $hash;
418
            }
419
        } else {
420
            // Or just return the hash if no rule exist yet.
421
            autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $ljid . '> with hash <' . $hash . '> has no rule yet', 3 );
422
            return $hash;
423
        }
424
    }
425
426
    public function ao_ccss_api_generate( $path, $debug, $dcode ) {
427
        // POST jobs to criticalcss.com and return responses
428
        // Get key and key status.
429
        global $ao_ccss_key;
430
        global $ao_ccss_keyst;
431
        $key        = $ao_ccss_key;
432
        $key_status = $ao_ccss_keyst;
433
434
        // Prepare full URL to request.
435
        global $ao_ccss_noptimize;
436
437
        $site_host = get_site_url();
438
        $site_path = parse_url( $site_host, PHP_URL_PATH );
439
440
        if ( ! empty( $site_path ) ) {
441
            $site_host = str_replace( $site_path, '', $site_host );
442
        }
443
444
        // Logic to bind to one domain to avoid site clones of sites would
445
        // automatically begin spawning requests to criticalcss.com which has
446
        // a per domain cost.
447
        global $ao_ccss_domain;
448
        if ( empty( $ao_ccss_domain ) ) {
449
            // first request being done, update option to allow future requests are only allowed if from same domain.
450
            update_option( 'autoptimize_ccss_domain', str_rot13( $site_host ) );
451
        } elseif ( trim( $ao_ccss_domain, '\'"' ) !== 'none' && parse_url( $site_host, PHP_URL_HOST ) !== parse_url( $ao_ccss_domain, PHP_URL_HOST ) && apply_filters( 'autoptimize_filter_ccss_bind_domain', true ) ) {
452
            // not the same domain, log as error and return without posting to criticalcss.com.
453
            autoptimizeCriticalCSSCore::ao_ccss_log( 'Request for domain ' . $site_host . ' does not match bound domain ' . $ao_ccss_domain . ' so not proceeding.', 2 );
454
            return false;
455
        }
456
457
        $src_url = $site_host . $path;
458
459
        // Avoid AO optimizations if required by config or avoid lazyload if lazyload is active in AO.
460
        if ( ! empty( $ao_ccss_noptimize ) ) {
461
            $src_url .= '?ao_noptirocket=1';
462
        } elseif ( class_exists( 'autoptimizeImages', false ) && autoptimizeImages::should_lazyload_wrapper() ) {
463
            $src_url .= '?ao_nolazy=1';
464
        }
465
466
        $src_url = apply_filters( 'autoptimize_filter_ccss_cron_srcurl', $src_url );
467
468
        // Initialize request body.
469
        $body           = array();
470
        $body['url']    = $src_url;
471
        $body['aff']    = 1;
472
        $body['aocssv'] = AO_CCSS_VER;
473
474
        // Prepare and add viewport size to the body if available.
475
        $viewport = autoptimizeCriticalCSSCore::ao_ccss_viewport();
476
        if ( ! empty( $viewport['w'] ) && ! empty( $viewport['h'] ) ) {
477
            $body['width']  = $viewport['w'];
478
            $body['height'] = $viewport['h'];
479
        }
480
481
        // Prepare and add forceInclude to the body if available.
482
        global $ao_ccss_finclude;
483
        $finclude = $this->ao_ccss_finclude( $ao_ccss_finclude );
484
        if ( ! empty( $finclude ) ) {
485
            $body['forceInclude'] = $finclude;
486
        }
487
488
        // Body must be json and log it.
489
        $body = json_encode( $body );
490
        autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: POST generate request body is ' . $body, 3 );
491
492
        // Prepare the request.
493
        $url  = esc_url_raw( AO_CCSS_API . 'generate?aover=' . AO_CCSS_VER );
494
        $args = array(
495
            'headers' => array(
496
                'User-Agent'    => 'Autoptimize v' . AO_CCSS_VER,
497
                'Content-type'  => 'application/json; charset=utf-8',
498
                'Authorization' => 'JWT ' . $key,
499
                'Connection'    => 'close',
500
            ),
501
            'body'    => $body,
502
        );
503
504
        // Dispatch the request and store its response code.
505
        $req  = wp_safe_remote_post( $url, $args );
506
        $code = wp_remote_retrieve_response_code( $req );
507
        $body = json_decode( wp_remote_retrieve_body( $req ), true );
508
509
        if ( $debug && $dcode ) {
510
            // If queue debug is active, change response code.
511
            $code = $dcode;
512
        }
513
514
        if ( 200 == $code ) {
515
            // Response code is OK.
516
            // Workaround criticalcss.com non-RESTful reponses.
517
            if ( 'JOB_QUEUED' == $body['job']['status'] || 'JOB_ONGOING' == $body['job']['status'] || 'STATUS_JOB_BAD' == $body['job']['status'] ) {
518
                // Log successful and return encoded request body.
519
                autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: POST generate request for path <' . $src_url . '> replied successfully', 3 );
520
521
                // This code also means the key is valid, so cache key status for 24h if not already cached.
522
                if ( ( ! $key_status || 2 != $key_status ) && $key ) {
523
                    update_option( 'autoptimize_ccss_keyst', 2 );
524
                    autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: API key is valid, updating key status', 3 );
525
                }
526
527
                // Return the request body.
528
                return $body;
529 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...
530
                // Log successful requests with invalid reponses.
531
                autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: POST generate request for path <' . $src_url . '> replied with code <' . $code . '> and an UNKNOWN error condition, body follows...', 2 );
532
                autoptimizeCriticalCSSCore::ao_ccss_log( print_r( $body, true ), 2 );
533
                return $body;
534
            }
535
        } else {
536
            // Response code is anything else.
537
            // Log failed request with a valid response code and return body.
538
            if ( $code ) {
539
                autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: POST generate request for path <' . $src_url . '> replied with error code <' . $code . '>, body follows...', 2 );
540
                autoptimizeCriticalCSSCore::ao_ccss_log( print_r( $body, true ), 2 );
541
542
                if ( 401 == $code ) {
543
                    // If request is unauthorized, also clear key status.
544
                    update_option( 'autoptimize_ccss_keyst', 1 );
545
                    autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: API key is invalid, updating key status', 3 );
546
                }
547
548
                // Return the request body.
549
                return $body;
550 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...
551
                // Log failed request with no response and return false.
552
                autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: POST generate request for path <' . $src_url . '> has no response, this could be a service timeout', 2 );
553
                if ( is_wp_error( $req ) ) {
554
                    autoptimizeCriticalCSSCore::ao_ccss_log( $req->get_error_message(), 2 );
555
                }
556
557
                return false;
558
            }
559
        }
560
    }
561
562
    public function ao_ccss_api_results( $jobid, $debug, $dcode ) {
563
        // GET jobs from criticalcss.com and return responses
564
        // Get key.
565
        global $ao_ccss_key;
566
        $key = $ao_ccss_key;
567
568
        // Prepare the request.
569
        $url  = AO_CCSS_API . 'results?resultId=' . $jobid;
570
        $args = array(
571
            'headers' => array(
572
                'User-Agent'    => 'Autoptimize CriticalCSS Power-Up v' . AO_CCSS_VER,
573
                'Authorization' => 'JWT ' . $key,
574
                'Connection'    => 'close',
575
            ),
576
        );
577
578
        // Dispatch the request and store its response code.
579
        $req  = wp_safe_remote_get( $url, $args );
580
        $code = wp_remote_retrieve_response_code( $req );
581
        $body = json_decode( wp_remote_retrieve_body( $req ), true );
582
583
        if ( $debug && $dcode ) {
584
            // If queue debug is active, change response code.
585
            $code = $dcode;
586
        }
587
588
        if ( 200 == $code ) {
589
            // Response code is OK.
590
            if ( is_array( $body ) && ( array_key_exists( 'status', $body ) || array_key_exists( 'job', $body ) ) && ( 'JOB_QUEUED' == $body['status'] || 'JOB_ONGOING' == $body['status'] || 'JOB_DONE' == $body['status'] || 'JOB_FAILED' == $body['status'] || 'JOB_UNKNOWN' == $body['status'] || 'STATUS_JOB_BAD' == $body['job']['status'] ) ) {
591
                // Workaround criticalcss.com non-RESTful reponses
592
                // Log successful and return encoded request body.
593
                autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> replied successfully', 3 );
594
                return $body;
595
            } elseif ( is_array( $body ) && ( array_key_exists( 'error', $body ) && 'This css no longer exists. Please re-generate it.' == $body['error'] ) ) {
596
                // Handle no CSS reply
597
                // Log no CSS error and return encoded request body.
598
                autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> replied successfully but the CSS for it does not exist anymore', 3 );
599
                return $body;
600 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...
601
                // Log failed request and return false.
602
                autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> replied with code <' . $code . '> and an UNKNOWN error condition, body follows...', 2 );
603
                autoptimizeCriticalCSSCore::ao_ccss_log( print_r( $body, true ), 2 );
604
                return false;
605
            }
606
        } else {
607
            // Response code is anything else
608
            // Log failed request with a valid response code and return body.
609
            if ( $code ) {
610
                autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> replied with error code <' . $code . '>, body follows...', 2 );
611
                autoptimizeCriticalCSSCore::ao_ccss_log( print_r( $body, true ), 2 );
612
                if ( 401 == $code ) {
613
                    // If request is unauthorized, also clear key status.
614
                    update_option( 'autoptimize_ccss_keyst', 1 );
615
                    autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: API key is invalid, updating key status', 3 );
616
                }
617
618
                // Return the request body.
619
                return $body;
620
            } else {
621
                // Log failed request with no response and return false.
622
                autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> has no response, this could be a service timeout', 2 );
623
                return false;
624
            }
625
        }
626
    }
627
628
    public function ao_ccss_save_file( $ccss, $target, $review ) {
629
        // Save critical CSS into the filesystem and return its filename
630
        // Prepare review mark.
631
        if ( $review ) {
632
            $rmark = '_R';
633
        } else {
634
            $rmark = '';
635
        }
636
637
        // Prepare target rule, filename and content.
638
        $filename = false;
639
        $content  = $ccss;
640
641
        if ( autoptimizeCriticalCSSCore::ao_ccss_check_contents( $content ) ) {
642
            // Sanitize content, set filename and try to save file.
643
            $file     = AO_CCSS_DIR . 'ccss_' . md5( $ccss . $target[1] ) . $rmark . '.css';
644
            $status   = file_put_contents( $file, $content, LOCK_EX );
645
            $filename = pathinfo( $file, PATHINFO_BASENAME );
646
            autoptimizeCriticalCSSCore::ao_ccss_log( 'Critical CSS file for the rule <' . $target[0] . '|' . $target[1] . '> was saved as <' . $filename . '>, size in bytes is <' . $status . '>', 3 );
647
648
            if ( ! $status ) {
649
                // If file has not been saved, reset filename.
650
                autoptimizeCriticalCSSCore::ao_ccss_log( 'Critical CSS file <' . $filename . '> could not be not saved', 2 );
651
                $filename = false;
652
                return $filename;
653
            }
654
        } else {
655
            autoptimizeCriticalCSSCore::ao_ccss_log( 'Critical CSS received did not pass content check', 2 );
656
            return $filename;
657
        }
658
659
        // Remove old critical CSS if a previous one existed in the rule and if that file exists in filesystem
660
        // NOTE: out of scope critical CSS file removal (issue #5)
661
        // Attach required arrays.
662
        global $ao_ccss_rules;
663
664
        // Prepare rule variables.
665
        $srule   = $ao_ccss_rules[ $target[0] ][ $target[1] ];
666
        $oldfile = $srule['file'];
667
668
        if ( $oldfile && $oldfile !== $filename ) {
669
            $delfile = AO_CCSS_DIR . $oldfile;
670
            if ( file_exists( $delfile ) ) {
671
                $unlinkst = unlink( $delfile );
672
                if ( $unlinkst ) {
673
                    autoptimizeCriticalCSSCore::ao_ccss_log( 'A previous critical CSS file <' . $oldfile . '> was removed for the rule <' . $target[0] . '|' . $target[1] . '>', 3 );
674
                }
675
            }
676
        }
677
678
        // Return filename or false.
679
        return $filename;
680
    }
681
682
    public function ao_ccss_rule_update( $ljid, $srule, $file, $hash ) {
683
        // Update or create a rule
684
        // Attach required arrays.
685
        global $ao_ccss_rules;
686
687
        // Prepare rule variables.
688
        $trule  = explode( '|', $srule );
689
        $rule   = $ao_ccss_rules[ $trule[0] ][ $trule[1] ];
690
        $action = false;
691
        $rtype  = '';
692
693
        if ( 0 === $rule['hash'] && 0 !== $rule['file'] ) {
694
            // manual rule, don't ever overwrite.
695
            $action = 'NOT UPDATED';
696
            $rtype  = 'MANUAL';
697
        } elseif ( 0 === $rule['hash'] && 0 === $rule['file'] ) {
698
            // If this is an user created AUTO rule with no hash and file yet, update its hash and filename
699
            // Set rule hash, file and action flag.
700
            $rule['hash'] = $hash;
701
            $rule['file'] = $file;
702
            $action       = 'UPDATED';
703
            $rtype        = 'AUTO';
704
        } elseif ( 0 !== $rule['hash'] && ctype_alnum( $rule['hash'] ) ) {
705
            // If this is an genuine AUTO rule, update its hash and filename
706
            // Set rule hash, file and action flag.
707
            $rule['hash'] = $hash;
708
            $rule['file'] = $file;
709
            $action       = 'UPDATED';
710
            $rtype        = 'AUTO';
711
        } else {
712
            // If rule doesn't exist, create an AUTO rule
713
            // AUTO rules were only for types, but will now also work for paths.
714
            if ( 'types' == $trule[0] || 'paths' == $trule[0] ) {
715
                // Set rule hash and file and action flag.
716
                $rule['hash'] = $hash;
717
                $rule['file'] = $file;
718
                $action       = 'CREATED';
719
                $rtype        = 'AUTO';
720
            } else {
721
                // Log that no rule was created.
722
                autoptimizeCriticalCSSCore::ao_ccss_log( 'Exception, no AUTO rule created', 3 );
723
            }
724
        }
725
726
        if ( $action ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $action 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...
727
            // If a rule creation/update is required, persist updated rules object.
728
            $ao_ccss_rules[ $trule[0] ][ $trule[1] ] = $rule;
729
            $ao_ccss_rules_raw                       = json_encode( $ao_ccss_rules );
730
            update_option( 'autoptimize_ccss_rules', $ao_ccss_rules_raw );
731
            autoptimizeCriticalCSSCore::ao_ccss_log( 'Target rule <' . $srule . '> of type <' . $rtype . '> was ' . $action . ' for job id <' . $ljid . '>', 3 );
732
        } else {
733
            autoptimizeCriticalCSSCore::ao_ccss_log( 'No rule action required', 3 );
734
        }
735
    }
736
737
    function ao_ccss_finclude( $finclude_raw ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
738
        // Prepare forceInclude object.
739
        if ( ! empty( $finclude_raw ) ) {
740
            // If there are any content
741
            // Convert raw string into arra and initialize the returning object.
742
            $fincludes = explode( ',', $finclude_raw );
743
            $finclude  = array();
744
745
            // Interacts over every rule.
746
            $i = 0;
747
            foreach ( $fincludes as $include ) {
748
                // Trim leading and trailing whitespaces.
749
                $include = trim( $include );
750
751
                if ( substr( $include, 0, 2 ) === '//' ) {
752
                    // Regex rule
753
                    // Format value as required.
754
                    $include = str_replace( '//', '/', $include );
755
                    $include = $include . '/i';
756
757
                    // Store regex object.
758
                    $finclude[ $i ]['type']  = 'RegExp';
759
                    $finclude[ $i ]['value'] = $include;
760
                } else {
761
                    // Simple value rule.
762
                    $finclude[ $i ]['value'] = $include;
763
                }
764
765
                $i++;
766
            }
767
768
            // Return forceInclude object.
769
            return $finclude;
770
        } else {
771
            // Or just return false if empty.
772
            return false;
773
        }
774
    }
775
776
    public static function ao_ccss_cleaning() {
777
        // Perform plugin maintenance
778
        // Truncate log file >= 1MB .
779
        if ( file_exists( AO_CCSS_LOG ) ) {
780
            if ( filesize( AO_CCSS_LOG ) >= 1048576 ) {
781
                $logfile = fopen( AO_CCSS_LOG, 'w' );
782
                fclose( $logfile );
783
            }
784
        }
785
786
        // Remove lock file.
787
        if ( file_exists( AO_CCSS_LOCK ) ) {
788
            unlink( AO_CCSS_LOCK );
789
        }
790
791
        // Make sure queue processing is scheduled, recreate if not.
792
        if ( ! wp_next_scheduled( 'ao_ccss_queue' ) ) {
793
            wp_schedule_event( time(), apply_filters( 'ao_ccss_queue_schedule', 'ao_ccss' ), 'ao_ccss_queue' );
794
        }
795
796
        // Queue cleaning.
797
        global $ao_ccss_queue;
798
        $queue_purge_threshold = 100;
799
        $queue_purge_age       = 24 * 60 * 60;
800
        $queue_length          = count( $ao_ccss_queue );
801
        $timestamp_yesterday   = microtime( true ) - $queue_purge_age;
802
        $remove_old_new        = false;
803
        $queue_altered         = false;
804
805
        if ( $queue_length > $queue_purge_threshold ) {
806
            $remove_old_new = true;
807
        }
808
809
        foreach ( $ao_ccss_queue as $path => $job ) {
810
            if ( ( $remove_old_new && 'NEW' == $job['jqstat'] && $job['jctime'] < $timestamp_yesterday ) || in_array( $job['jqstat'], array( 'JOB_FAILED', 'STATUS_JOB_BAD', 'NO_CSS', 'NO_RESPONSE' ) ) ) {
811
                unset( $ao_ccss_queue[ $path ] );
812
                $queue_altered = true;
813
            }
814
        }
815
816
        // save queue to options!
817
        if ( $queue_altered ) {
818
            $ao_ccss_queue_raw = json_encode( $ao_ccss_queue );
819
            update_option( 'autoptimize_ccss_queue', $ao_ccss_queue_raw, false );
820
            autoptimizeCriticalCSSCore::ao_ccss_log( 'Queue cleaning done.', 3 );
821
        }
822
823
        // re-check key if invalid.
824
        global $ao_ccss_keyst;
825
        if ( 1 == $ao_ccss_keyst ) {
826
            $this->ao_ccss_api_generate( '', '', '' );
0 ignored issues
show
Bug introduced by
The variable $this 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...
827
        }
828
    }
829
}
830