Completed
Push — master ( 5b581f...5da188 )
by frank
04:46
created

ao_ccss_define_job()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 9
dl 0
loc 29
rs 9.456
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * Critical CSS job enqueue logic.
4
 */
5
6
if ( ! defined( 'ABSPATH' ) ) {
7
    exit;
8
}
9
10
class autoptimizeCriticalCSSEnqueue {
11
    public function __construct()
12
    {
13
        // fetch all options at once and populate them individually explicitely as globals.
14
        $all_options = autoptimizeCriticalCSSBase::fetch_options();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $all_options is correct as \autoptimizeCriticalCSSBase::fetch_options() (which targets autoptimizeCriticalCSSBase::fetch_options()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
15
        foreach ( $all_options as $_option => $_value ) {
0 ignored issues
show
Bug introduced by
The expression $all_options of type null is not traversable.
Loading history...
16
            global ${$_option};
17
            ${$_option} = $_value;
18
        }
19
    }
20
21
    public static function ao_ccss_enqueue( $hash ) {
22
        $self = new self();
23
        // Get key status.
24
        $key = autoptimizeCriticalCSSCore::ao_ccss_key_status( false );
25
26
        // Queue is available to anyone...
27
        $enqueue = true;
28
29
        // ... which are not the ones below.
30
        if ( is_user_logged_in() || is_feed() || is_404() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) || $self->ao_ccss_ua() || 'nokey' == $key['status'] || 'invalid' == $key['status'] || false === apply_filters( 'autoptimize_filter_ccss_enqueue_should_enqueue', true ) ) {
31
            $enqueue = false;
32
            autoptimizeCriticalCSSCore::ao_ccss_log( "Job queuing is not available for WordPress's logged in users, feeds, error pages, ajax calls, to criticalcss.com itself or when a valid API key is not found", 3 );
33
        }
34
35
        if ( $enqueue ) {
36
            // Continue if queue is available
37
            // Attach required arrays/ vars.
38
            global $ao_ccss_rules;
39
            global $ao_ccss_queue_raw;
40
            global $ao_ccss_queue;
41
            global $ao_ccss_forcepath;
42
43
            // Get request path and page type, and initialize the queue update flag.
44
            $req_path        = strtok( $_SERVER['REQUEST_URI'], '?' );
45
            $req_type        = $self->ao_ccss_get_type();
46
            $job_qualify     = false;
47
            $target_rule     = false;
48
            $rule_properties = false;
49
            $queue_update    = false;
50
51
            // Match for paths in rules.
52
            foreach ( $ao_ccss_rules['paths'] as $path => $props ) {
53
54
                // Prepare rule target and log.
55
                $target_rule = 'paths|' . $path;
56
                autoptimizeCriticalCSSCore::ao_ccss_log( 'Qualifying path <' . $req_path . '> for job submission by rule <' . $target_rule . '>', 3 );
57
58
                // Path match
59
                // -> exact match needed for AUTO rules
60
                // -> partial match OK for MANUAL rules (which have empty hash and a file with CCSS).
61
                if ( $path === $req_path || ( false == $props['hash'] && false != $props['file'] && preg_match( '|' . $path . '|', $req_path ) ) ) {
62
63
                    // There's a path match in the rule, so job QUALIFIES with a path rule match.
64
                    $job_qualify     = true;
65
                    $rule_properties = $props;
66
                    autoptimizeCriticalCSSCore::ao_ccss_log( 'Path <' . $req_path . '> QUALIFIED for job submission by rule <' . $target_rule . '>', 3 );
67
68
                    // Stop processing other path rules.
69
                    break;
70
                }
71
            }
72
73
            // Match for types in rules if no path rule matches and if we're not enforcing paths.
74
            if ( ! $job_qualify && ( ! $ao_ccss_forcepath || ! in_array( $req_type, apply_filters( 'autoptimize_filter_ccss_coreenqueue_forcepathfortype', array( 'is_page' ) ) ) || ! apply_filters( 'autoptimize_filter_ccss_coreenqueue_ignorealltypes', false ) ) ) {
75
                foreach ( $ao_ccss_rules['types'] as $type => $props ) {
76
77
                    // Prepare rule target and log.
78
                    $target_rule = 'types|' . $type;
79
                    autoptimizeCriticalCSSCore::ao_ccss_log( 'Qualifying page type <' . $req_type . '> on path <' . $req_path . '> for job submission by rule <' . $target_rule . '>', 3 );
80
81
                    if ( $req_type == $type ) {
82
                        // Type match.
83
                        // There's a type match in the rule, so job QUALIFIES with a type rule match.
84
                        $job_qualify     = true;
85
                        $rule_properties = $props;
86
                        autoptimizeCriticalCSSCore::ao_ccss_log( 'Page type <' . $req_type . '> on path <' . $req_path . '> QUALIFIED for job submission by rule <' . $target_rule . '>', 3 );
87
88
                        // Stop processing other type rules.
89
                        break;
90
                    }
91
                }
92
            }
93
94
            if ( $job_qualify && ( ( false == $rule_properties['hash'] && false != $rule_properties['file'] ) || strpos( $req_type, 'template_' ) !== false ) ) {
95
                // If job qualifies but rule hash is false and file isn't false (MANUAL rule) or if template, job does not qualify despite what previous evaluations says.
96
                $job_qualify = false;
97
                autoptimizeCriticalCSSCore::ao_ccss_log( 'Job submission DISQUALIFIED by MANUAL rule <' . $target_rule . '> with hash <' . $rule_properties['hash'] . '> and file <' . $rule_properties['file'] . '>', 3 );
98
            } elseif ( ! $job_qualify && empty( $rule_properties ) ) {
99
                // But if job does not qualify and rule properties are set, job qualifies as there is no matching rule for it yet
100
                // Fill-in the new target rule.
101
                $job_qualify = true;
102
103
                // Should we switch to path-base AUTO-rules? Conditions:
104
                // 1. forcepath option has to be enabled (off by default)
105
                // 2. request type should be (by default, but filterable) one of is_page (removed for now: woo_is_product or woo_is_product_category).
106
                if ( ( $ao_ccss_forcepath && in_array( $req_type, apply_filters( 'autoptimize_filter_ccss_coreenqueue_forcepathfortype', array( 'is_page' ) ) ) ) || apply_filters( 'autoptimize_filter_ccss_coreenqueue_ignorealltypes', false ) ) {
107
                    if ( '/' !== $req_path ) {
108
                        $target_rule = 'paths|' . $req_path;
109
                    } else {
110
                        // Exception; we don't want a path-based rule for "/" as that messes things up, hard-switch this to a type-based is_front_page rule.
111
                        $target_rule = 'types|' . 'is_front_page';
112
                    }
113
                } else {
114
                    $target_rule = 'types|' . $req_type;
115
                }
116
                autoptimizeCriticalCSSCore::ao_ccss_log( 'Job submission QUALIFIED by MISSING rule for page type <' . $req_type . '> on path <' . $req_path . '>, new rule target is <' . $target_rule . '>', 3 );
117
            } else {
118
                // Or just log a job qualified by a matching rule.
119
                autoptimizeCriticalCSSCore::ao_ccss_log( 'Job submission QUALIFIED by AUTO rule <' . $target_rule . '> with hash <' . $rule_properties['hash'] . '> and file <' . $rule_properties['file'] . '>', 3 );
120
            }
121
122
            // Submit job.
123
            if ( $job_qualify ) {
124
                if ( ! array_key_exists( $req_path, $ao_ccss_queue ) ) {
125
                    // This is a NEW job
126
                    // Merge job into the queue.
127
                    $ao_ccss_queue[ $req_path ] = $self->ao_ccss_define_job(
128
                        $req_path,
129
                        $target_rule,
130
                        $req_type,
131
                        $hash,
132
                        null,
133
                        null,
134
                        null,
135
                        null,
136
                        true
137
                    );
138
                    // Set update flag.
139
                    $queue_update = true;
140
                } else {
141
                    // This is an existing job
142
                    // The job is still NEW, most likely this is extra CSS file for the same page that needs a hash.
143
                    if ( 'NEW' == $ao_ccss_queue[ $req_path ]['jqstat'] ) {
144
                        // Add hash if it's not already in the job.
145
                        if ( ! in_array( $hash, $ao_ccss_queue[ $req_path ]['hashes'] ) ) {
146
                            // Push new hash to its array and update flag.
147
                            $queue_update = array_push( $ao_ccss_queue[ $req_path ]['hashes'], $hash );
0 ignored issues
show
Unused Code introduced by
$queue_update 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...
148
149
                            // Log job update.
150
                            autoptimizeCriticalCSSCore::ao_ccss_log( 'Hashes UPDATED on local job id <' . $ao_ccss_queue[ $req_path ]['ljid'] . '>, job status NEW, target rule <' . $ao_ccss_queue[ $req_path ]['rtarget'] . '>, hash added: ' . $hash, 3 );
151
152
                            // Return from here as the hash array is already updated.
153
                            return true;
154
                        }
155
                    } elseif ( 'NEW' != $ao_ccss_queue[ $req_path ]['jqstat'] && 'JOB_QUEUED' != $ao_ccss_queue[ $req_path ]['jqstat'] && 'JOB_ONGOING' != $ao_ccss_queue[ $req_path ]['jqstat'] ) {
156
                        // Allow requeuing jobs that are not NEW, JOB_QUEUED or JOB_ONGOING
157
                        // Merge new job keeping some previous job values.
158
                        $ao_ccss_queue[ $req_path ] = $self->ao_ccss_define_job(
159
                            $req_path,
160
                            $target_rule,
161
                            $req_type,
162
                            $hash,
163
                            $ao_ccss_queue[ $req_path ]['file'],
164
                            $ao_ccss_queue[ $req_path ]['jid'],
165
                            $ao_ccss_queue[ $req_path ]['jrstat'],
166
                            $ao_ccss_queue[ $req_path ]['jvstat'],
167
                            false
168
                        );
169
                        // Set update flag.
170
                        $queue_update = true;
171
                    }
172
                }
173
174
                if ( $queue_update ) {
175
                    // Persist the job to the queue and return.
176
                    $ao_ccss_queue_raw = json_encode( $ao_ccss_queue );
177
                    update_option( 'autoptimize_ccss_queue', $ao_ccss_queue_raw, false );
178
                    return true;
179
                } else {
180
                    // Or just return false if no job was added.
181
                    autoptimizeCriticalCSSCore::ao_ccss_log( 'A job for path <' . $req_path . '> already exist with NEW or PENDING status, skipping job creation', 3 );
182
                    return false;
183
                }
184
            }
185
        }
186
    }
187
188
    public function ao_ccss_get_type() {
189
        // Get the type of a page
190
        // Attach the conditional tags array.
191
        global $ao_ccss_types;
192
193
        // By default, a page type is false.
194
        $page_type = false;
195
196
        // Iterates over the array to match a type.
197
        foreach ( $ao_ccss_types as $type ) {
198
            if ( is_404() ) {
199
                $page_type = 'is_404';
200
                break;
201
            } elseif ( strpos( $type, 'custom_post_' ) !== false ) {
202
                // Match custom post types.
203
                if ( get_post_type( get_the_ID() ) === substr( $type, 12 ) ) {
204
                    $page_type = $type;
205
                    break;
206
                }
207
            } elseif ( strpos( $type, 'template_' ) !== false ) {
208
                // Match templates.
209
                if ( is_page_template( substr( $type, 9 ) ) ) {
210
                    $page_type = $type;
211
                    break;
212
                }
213
            } else {
214
                // Match all other existing types
215
                // but remove prefix to be able to check if the function exists & returns true.
216
                $_type = str_replace( array( 'woo_', 'bp_', 'bbp_', 'edd_' ), '', $type );
217
                if ( function_exists( $_type ) && call_user_func( $_type ) ) {
218
                    // Make sure we only return is_front_page (and is_home) for one page, not for the "paged frontpage" (/page/2 ..).
219
                    if ( ( 'is_front_page' !== $_type && 'is_home' !== $_type ) || ! is_paged() ) {
220
                        $page_type = $type;
221
                        break;
222
                    }
223
                }
224
            }
225
        }
226
227
        // Return the page type.
228
        return $page_type;
229
    }
230
231
    public function ao_ccss_define_job( $path, $target, $type, $hash, $file, $jid, $jrstat, $jvstat, $create ) {
0 ignored issues
show
Unused Code introduced by
The parameter $path 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...
232
        // Define a job entry to be created or updated
233
        // Define commom job properties.
234
        $path            = array();
235
        $path['ljid']    = $this->ao_ccss_job_id();
236
        $path['rtarget'] = $target;
237
        $path['ptype']   = $type;
238
        $path['hashes']  = array( $hash );
239
        $path['hash']    = $hash;
240
        $path['file']    = $file;
241
        $path['jid']     = $jid;
242
        $path['jqstat']  = 'NEW';
243
        $path['jrstat']  = $jrstat;
244
        $path['jvstat']  = $jvstat;
245
        $path['jctime']  = microtime( true );
246
        $path['jftime']  = null;
247
248
        // Set operation requested.
249
        if ( $create ) {
250
            $operation = 'CREATED';
251
        } else {
252
            $operation = 'UPDATED';
253
        }
254
255
        // Log job creation.
256
        autoptimizeCriticalCSSCore::ao_ccss_log( 'Job ' . $operation . ' with local job id <' . $path['ljid'] . '> for target rule <' . $target . '>', 3 );
257
258
        return $path;
259
    }
260
261
    public function ao_ccss_job_id( $length = 6 ) {
262
        // Generate random strings for the local job ID
263
        // Based on https://stackoverflow.com/a/4356295 .
264
        $characters        = '0123456789abcdefghijklmnopqrstuvwxyz';
265
        $characters_length = strlen( $characters );
266
        $random_string     = 'j-';
267
        for ( $i = 0; $i < $length; $i++ ) {
268
            $random_string .= $characters[ rand( 0, $characters_length - 1 ) ];
269
        }
270
        return $random_string;
271
    }
272
273
    public function ao_ccss_ua() {
274
        // Check for criticalcss.com user agent.
275
        $agent = '';
276
        if ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) {
277
            $agent = $_SERVER['HTTP_USER_AGENT'];
278
        }
279
280
        // Check for UA and return TRUE when criticalcss.com is the detected UA, false when not.
281
        $rtn = strpos( $agent, AO_CCSS_URL );
282
        if ( 0 === $rtn ) {
283
            $rtn = true;
284
        } else {
285
            $rtn = false;
286
        }
287
        return ( $rtn );
288
    }
289
}
290