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

autoptimizeCriticalCSSSettingsAjax::run()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
1
<?php
2
/**
3
 * Critical CSS settings AJAX logic.
4
 */
5
6
if ( ! defined( 'ABSPATH' ) ) {
7
    exit;
8
}
9
10
class autoptimizeCriticalCSSSettingsAjax {
11 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...
12
    {
13
        // fetch all options at once and populate them individually explicitely as globals.
14
        $all_options = autoptimizeCriticalCSSBase::fetch_options();
15
        foreach ( $all_options as $_option => $_value ) {
16
            global ${$_option};
17
            ${$_option} = $_value;
18
        }
19
        $this->run();
20
    }
21
22
    public function run() {
23
        // add filters.
24
        add_action( 'wp_ajax_fetch_critcss', array( $this, 'critcss_fetch_callback' ) );
25
        add_action( 'wp_ajax_save_critcss', array( $this, 'critcss_save_callback' ) );
26
        add_action( 'wp_ajax_rm_critcss', array( $this, 'critcss_rm_callback' ) );
27
        add_action( 'wp_ajax_rm_critcss_all', array( $this, 'critcss_rm_all_callback' ) );
28
        add_action( 'wp_ajax_ao_ccss_export', array( $this, 'ao_ccss_export_callback' ) );
29
        add_action( 'wp_ajax_ao_ccss_import', array( $this, 'ao_ccss_import_callback' ) );
30
    }
31
32
    public function critcss_fetch_callback() {
33
        // Ajax handler to obtain a critical CSS file from the filesystem.
34
        // Check referer.
35
        check_ajax_referer( 'fetch_critcss_nonce', 'critcss_fetch_nonce' );
36
37
        // Initialize error flag.
38
        $error = true;
39
40
        // Allow no content for MANUAL rules (as they may not exist just yet).
41 View Code Duplication
        if ( current_user_can( 'manage_options' ) && empty( $_POST['critcssfile'] ) ) {
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...
42
            $content = '';
43
            $error   = false;
44
        } elseif ( current_user_can( 'manage_options' ) && $this->critcss_check_filename( $_POST['critcssfile'] ) ) {
45
            // Or check user permissios and filename.
46
            // Set file path and obtain its content.
47
            $critcssfile = AO_CCSS_DIR . strip_tags( $_POST['critcssfile'] );
48
            if ( file_exists( $critcssfile ) ) {
49
                $content = file_get_contents( $critcssfile );
50
                $error   = false;
51
            }
52
        }
53
54
        // Prepare response.
55
        if ( $error ) {
56
            $response['code']   = '500';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$response was never initialized. Although not strictly required by PHP, it is generally a good practice to add $response = 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...
57
            $response['string'] = 'Error reading file ' . $critcssfile . '.';
0 ignored issues
show
Bug introduced by
The variable $critcssfile 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...
58
        } else {
59
            $response['code']   = '200';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$response was never initialized. Although not strictly required by PHP, it is generally a good practice to add $response = 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...
60
            $response['string'] = $content;
0 ignored issues
show
Bug introduced by
The variable $content 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...
61
        }
62
63
        // Dispatch respose.
64
        echo json_encode( $response );
65
66
        // Close ajax request.
67
        wp_die();
68
    }
69
70
    public function critcss_save_callback() {
71
        $error    = false;
72
        $status   = false;
73
        $response = array();
74
75
        // Ajax handler to write a critical CSS to the filesystem
76
        // Check referer.
77
        check_ajax_referer( 'save_critcss_nonce', 'critcss_save_nonce' );
78
79
        // Allow empty contents for MANUAL rules (as they are fetched later).
80
        if ( current_user_can( 'manage_options' ) && empty( $_POST['critcssfile'] ) ) {
81
            $critcssfile = false;
82
            $status      = true;
83
        } elseif ( current_user_can( 'manage_options' ) && $this->critcss_check_filename( $_POST['critcssfile'] ) ) {
84
            // Or check user permissios and filename
85
            // Set critical CSS content.
86
            $critcsscontents = stripslashes( $_POST['critcsscontents'] );
87
88
            // If there is content and it's valid, write the file.
89
            if ( $critcsscontents && autoptimizeCriticalCSSCore::ao_ccss_check_contents( $critcsscontents ) ) {
90
                // Set file path and status.
91
                $critcssfile = AO_CCSS_DIR . strip_tags( $_POST['critcssfile'] );
92
                $status      = file_put_contents( $critcssfile, $critcsscontents, LOCK_EX );
93
                // Or set as error.
94
            } else {
95
                $error = true;
96
            }
97
            // Or just set an error.
98
        } else {
99
            $error = true;
100
        }
101
102
        // Prepare response.
103 View Code Duplication
        if ( ! $status || $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...
104
            $response['code']   = '500';
105
            $response['string'] = 'Error saving file ' . $critcssfile . '.';
0 ignored issues
show
Bug introduced by
The variable $critcssfile 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...
106
        } else {
107
            $response['code'] = '200';
108
            if ( $critcssfile ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $critcssfile of type false|string 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...
109
                $response['string'] = 'File ' . $critcssfile . ' saved.';
110
            } else {
111
                $response['string'] = 'Empty content do not need to be saved.';
112
            }
113
        }
114
115
        // Dispatch respose.
116
        echo json_encode( $response );
117
118
        // Close ajax request.
119
        wp_die();
120
    }
121
122
123
    public function critcss_rm_callback() {
124
        // Ajax handler to delete a critical CSS from the filesystem
125
        // Check referer.
126
        check_ajax_referer( 'rm_critcss_nonce', 'critcss_rm_nonce' );
127
128
        // Initialize error and status flags.
129
        $error  = true;
130
        $status = false;
131
132
        // Allow no file for MANUAL rules (as they may not exist just yet).
133 View Code Duplication
        if ( current_user_can( 'manage_options' ) && empty( $_POST['critcssfile'] ) ) {
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...
134
            $error = false;
135
        } elseif ( current_user_can( 'manage_options' ) && $this->critcss_check_filename( $_POST['critcssfile'] ) ) {
136
            // Or check user permissios and filename
137
            // Set file path and delete it.
138
            $critcssfile = AO_CCSS_DIR . strip_tags( $_POST['critcssfile'] );
139
            if ( file_exists( $critcssfile ) ) {
140
                $status = unlink( $critcssfile );
141
                $error  = false;
142
            }
143
        }
144
145
        // Prepare response.
146 View Code Duplication
        if ( $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...
147
            $response['code']   = '500';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$response was never initialized. Although not strictly required by PHP, it is generally a good practice to add $response = 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...
148
            $response['string'] = 'Error removing file ' . $critcssfile . '.';
0 ignored issues
show
Bug introduced by
The variable $critcssfile 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...
149
        } else {
150
            $response['code'] = '200';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$response was never initialized. Although not strictly required by PHP, it is generally a good practice to add $response = 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...
151
            if ( $status ) {
152
                $response['string'] = 'File ' . $critcssfile . ' removed.';
153
            } else {
154
                $response['string'] = 'No file to be removed.';
155
            }
156
        }
157
158
        // Dispatch respose.
159
        echo json_encode( $response );
160
161
        // Close ajax request.
162
        wp_die();
163
    }
164
165
    public function critcss_rm_all_callback() {
166
        // Ajax handler to delete a critical CSS from the filesystem
167
        // Check referer.
168
        check_ajax_referer( 'rm_critcss_all_nonce', 'critcss_rm_all_nonce' );
169
170
        // Initialize error and status flags.
171
        $error  = true;
172
        $status = false;
173
174
        // Remove all ccss files on filesystem.
175
        if ( current_user_can( 'manage_options' ) ) {
176
            if ( file_exists( AO_CCSS_DIR ) && is_dir( AO_CCSS_DIR ) ) {
177
                array_map( 'unlink', glob( AO_CCSS_DIR . 'ccss_*.css', GLOB_BRACE ) );
178
                $error  = false;
179
                $status = true;
180
            }
181
        }
182
183
        // Prepare response.
184
        if ( $error ) {
185
            $response['code']   = '500';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$response was never initialized. Although not strictly required by PHP, it is generally a good practice to add $response = 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...
186
            $response['string'] = 'Error removing all critical CSS files.';
187
        } else {
188
            $response['code'] = '200';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$response was never initialized. Although not strictly required by PHP, it is generally a good practice to add $response = 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...
189
            if ( $status ) {
190
                $response['string'] = 'Critical CSS Files removed.';
191
            } else {
192
                $response['string'] = 'No file removed.';
193
            }
194
        }
195
196
        // Dispatch respose.
197
        echo json_encode( $response );
198
199
        // Close ajax request.
200
        wp_die();
201
    }
202
203
    public function ao_ccss_export_callback() {
204
        // Ajax handler export settings
205
        // Check referer.
206
        check_ajax_referer( 'ao_ccss_export_nonce', 'ao_ccss_export_nonce' );
207
208
        if ( ! class_exists( 'ZipArchive' ) ) {
209
            $response['code'] = '500';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$response was never initialized. Although not strictly required by PHP, it is generally a good practice to add $response = 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...
210
            $response['msg']  = 'PHP ZipArchive not present, cannot create zipfile';
211
            echo json_encode( $response );
212
            wp_die();
213
        }
214
215
        // Init array, get options and prepare the raw object.
216
        $settings               = array();
217
        $settings['rules']      = get_option( 'autoptimize_ccss_rules' );
218
        $settings['additional'] = get_option( 'autoptimize_ccss_additional' );
219
        $settings['viewport']   = get_option( 'autoptimize_ccss_viewport' );
220
        $settings['finclude']   = get_option( 'autoptimize_ccss_finclude' );
221
        $settings['rlimit']     = get_option( 'autoptimize_ccss_rlimit' );
222
        $settings['noptimize']  = get_option( 'autoptimize_ccss_noptimize' );
223
        $settings['debug']      = get_option( 'autoptimize_ccss_debug' );
224
        $settings['key']        = get_option( 'autoptimize_ccss_key' );
225
226
        // Initialize error flag.
227
        $error = true;
228
229
        // Check user permissions.
230
        if ( current_user_can( 'manage_options' ) ) {
231
            // Prepare settings file path and content.
232
            $exportfile = AO_CCSS_DIR . 'settings.json';
233
            $contents   = json_encode( $settings );
234
            $status     = file_put_contents( $exportfile, $contents, LOCK_EX );
235
            $error      = false;
236
        }
237
238
        // Prepare archive.
239
        $zipfile = AO_CCSS_DIR . date( 'Ymd-H\hi' ) . '_ao_ccss_settings.zip';
240
        $file    = pathinfo( $zipfile, PATHINFO_BASENAME );
241
        $zip     = new ZipArchive();
242
        $ret     = $zip->open( $zipfile, ZipArchive::CREATE );
243
        if ( true !== $ret ) {
244
            $error = true;
245
        } else {
246
            $zip->addFile( AO_CCSS_DIR . 'settings.json', 'settings.json' );
247
            if ( file_exists( AO_CCSS_DIR . 'queue.json' ) ) {
248
                $zip->addFile( AO_CCSS_DIR . 'queue.json', 'queue.json' );
249
            }
250
            $options = array(
251
                'add_path'        => './',
252
                'remove_all_path' => true,
253
            );
254
            $zip->addGlob( AO_CCSS_DIR . '*.css', 0, $options );
255
            $zip->close();
256
        }
257
258
        // Prepare response.
259 View Code Duplication
        if ( ! $status || $error ) {
0 ignored issues
show
Bug introduced by
The variable $status 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...
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...
260
            $response['code'] = '500';
0 ignored issues
show
Bug introduced by
The variable $response 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...
261
            $response['msg']  = 'Error saving file ' . $file . ', code: ' . $ret;
262
        } else {
263
            $response['code'] = '200';
264
            $response['msg']  = 'File ' . $file . ' saved.';
265
            $response['file'] = $file;
266
        }
267
268
        // Dispatch respose.
269
        echo json_encode( $response );
270
271
        // Close ajax request.
272
        wp_die();
273
    }
274
275
    public function ao_ccss_import_callback() {
276
        // Ajax handler import settings
277
        // Check referer.
278
        check_ajax_referer( 'ao_ccss_import_nonce', 'ao_ccss_import_nonce' );
279
280
        // Initialize error flag.
281
        $error = false;
282
283
        // Process an uploaded file with no errors.
284
        if ( ! $_FILES['file']['error'] ) {
285
            // Save file to the cache directory.
286
            $zipfile = AO_CCSS_DIR . $_FILES['file']['name'];
287
            move_uploaded_file( $_FILES['file']['tmp_name'], $zipfile );
288
289
            // Extract archive.
290
            $zip = new ZipArchive;
291
            if ( $zip->open( $zipfile ) === true ) {
292
                $zip->extractTo( AO_CCSS_DIR );
293
                $zip->close();
294
            } else {
295
                $error = 'extracting';
296
            }
297
298
            if ( ! $error ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $error of type false|string is loosely compared to false; 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...
299
                // Archive extraction ok, continue settings importing
300
                // Settings file.
301
                $importfile = AO_CCSS_DIR . 'settings.json';
302
303
                if ( file_exists( $importfile ) ) {
304
                    // Get settings and turn them into an object.
305
                    $settings = json_decode( file_get_contents( $importfile ), true );
306
307
                    // Update options.
308
                    update_option( 'autoptimize_ccss_rules', $settings['rules'] );
309
                    update_option( 'autoptimize_ccss_additional', $settings['additional'] );
310
                    update_option( 'autoptimize_ccss_viewport', $settings['viewport'] );
311
                    update_option( 'autoptimize_ccss_finclude', $settings['finclude'] );
312
                    update_option( 'autoptimize_ccss_rlimit', $settings['rlimit'] );
313
                    update_option( 'autoptimize_ccss_noptimize', $settings['noptimize'] );
314
                    update_option( 'autoptimize_ccss_debug', $settings['debug'] );
315
                    update_option( 'autoptimize_ccss_key', $settings['key'] );
316
                } else {
317
                    // Settings file doesn't exist, update error flag.
318
                    $error = 'settings file does not exist';
319
                }
320
            }
321
        }
322
323
        // Prepare response.
324
        if ( $error ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $error of type false|string 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...
325
            $response['code'] = '500';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$response was never initialized. Although not strictly required by PHP, it is generally a good practice to add $response = 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...
326
            $response['msg']  = 'Error importing settings: ' . $error;
327
        } else {
328
            $response['code'] = '200';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$response was never initialized. Although not strictly required by PHP, it is generally a good practice to add $response = 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...
329
            $response['msg']  = 'Settings imported successfully';
330
        }
331
332
        // Dispatch respose.
333
        echo json_encode( $response );
334
335
        // Close ajax request.
336
        wp_die();
337
    }
338
339
    public function critcss_check_filename( $filename ) {
340
        // Try to avoid directory traversal when reading/writing/deleting critical CSS files.
341
        if ( strpos( $filename, 'ccss_' ) !== 0 ) {
342
            return false;
343
        } elseif ( substr( $filename, -4, 4 ) !== '.css' ) {
344
            return false;
345
        } elseif ( sanitize_file_name( $filename ) !== $filename ) {
346
            // Use WordPress core's sanitize_file_name to see if anything fishy is going on.
347
            return false;
348
        } else {
349
            return true;
350
        }
351
    }
352
}
353