Completed
Push — master ( cf90b7...5795fc )
by Michael
02:22
created

System::cat()   D

Complexity

Conditions 12
Paths 168

Size

Total Lines 49
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 36
nc 168
nop 1
dl 0
loc 49
rs 4.8187
c 0
b 0
f 0

How to fix   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
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 58 and the first side effect is on line 19.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * File/Directory manipulation
4
 *
5
 * PHP versions 4 and 5
6
 *
7
 * @category   pear
8
 * @package    System
9
 * @author     Tomas V.V.Cox <[email protected]>
10
 * @copyright  1997-2009 The Authors
11
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
12
 * @link       http://pear.php.net/package/PEAR
13
 * @since      File available since Release 0.1
14
 */
15
16
/**
17
 * base class
18
 */
19
require_once 'PEAR.php';
20
require_once 'Console/Getopt.php';
21
22
$GLOBALS['_System_temp_files'] = array();
23
24
/**
25
* System offers cross platform compatible system functions
26
*
27
* Static functions for different operations. Should work under
28
* Unix and Windows. The names and usage has been taken from its respectively
29
* GNU commands. The functions will return (bool) false on error and will
30
* trigger the error with the PHP trigger_error() function (you can silence
31
* the error by prefixing a '@' sign after the function call, but this
32
* is not recommended practice.  Instead use an error handler with
33
* {@link set_error_handler()}).
34
*
35
* Documentation on this class you can find in:
36
* http://pear.php.net/manual/
37
*
38
* Example usage:
39
* if (!@System::rm('-r file1 dir1')) {
40
*    print "could not delete file1 or dir1";
41
* }
42
*
43
* In case you need to to pass file names with spaces,
44
* pass the params as an array:
45
*
46
* System::rm(array('-r', $file1, $dir1));
47
*
48
* @category   pear
49
* @package    System
50
* @author     Tomas V.V. Cox <[email protected]>
51
* @copyright  1997-2006 The PHP Group
52
* @license    http://opensource.org/licenses/bsd-license.php New BSD License
53
* @version    Release: 1.10.5
54
* @link       http://pear.php.net/package/PEAR
55
* @since      Class available since Release 0.1
56
* @static
57
*/
58
class System
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
59
{
60
    /**
61
     * returns the commandline arguments of a function
62
     *
63
     * @param    string  $argv           the commandline
64
     * @param    string  $short_options  the allowed option short-tags
65
     * @param    string  $long_options   the allowed option long-tags
0 ignored issues
show
Documentation introduced by
Should the type for parameter $long_options not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
66
     * @return   array   the given options and there values
67
     */
68
    public static function _parseArgs($argv, $short_options, $long_options = null)
69
    {
70
        if (!is_array($argv) && $argv !== null) {
71
            /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
48% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
72
            // Quote all items that are a short option
73
            $av = preg_split('/(\A| )--?[a-z0-9]+[ =]?((?<!\\\\)((,\s*)|((?<!,)\s+))?)/i', $argv, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);
74
            $offset = 0;
75
            foreach ($av as $a) {
76
                $b = trim($a[0]);
77
                if ($b{0} == '"' || $b{0} == "'") {
78
                    continue;
79
                }
80
81
                $escape = escapeshellarg($b);
82
                $pos = $a[1] + $offset;
83
                $argv = substr_replace($argv, $escape, $pos, strlen($b));
84
                $offset += 2;
85
            }
86
            */
87
88
            // Find all items, quoted or otherwise
89
            preg_match_all("/(?:[\"'])(.*?)(?:['\"])|([^\s]+)/", $argv, $av);
90
            $argv = $av[1];
91
            foreach ($av[2] as $k => $a) {
92
                if (empty($a)) {
93
                    continue;
94
                }
95
                $argv[$k] = trim($a) ;
96
            }
97
        }
98
99
        return Console_Getopt::getopt2($argv, $short_options, $long_options);
100
    }
101
102
    /**
103
     * Output errors with PHP trigger_error(). You can silence the errors
104
     * with prefixing a "@" sign to the function call: @System::mkdir(..);
105
     *
106
     * @param mixed $error a PEAR error or a string with the error message
107
     * @return bool false
108
     */
109
    protected static function raiseError($error)
110
    {
111
        if (PEAR::isError($error)) {
112
            $error = $error->getMessage();
113
        }
114
        trigger_error($error, E_USER_WARNING);
115
        return false;
116
    }
117
118
    /**
119
     * Creates a nested array representing the structure of a directory
120
     *
121
     * System::_dirToStruct('dir1', 0) =>
122
     *   Array
123
     *    (
124
     *    [dirs] => Array
125
     *        (
126
     *            [0] => dir1
127
     *        )
128
     *
129
     *    [files] => Array
130
     *        (
131
     *            [0] => dir1/file2
132
     *            [1] => dir1/file3
133
     *        )
134
     *    )
135
     * @param    string  $sPath      Name of the directory
136
     * @param    integer $maxinst    max. deep of the lookup
137
     * @param    integer $aktinst    starting deep of the lookup
138
     * @param    bool    $silent     if true, do not emit errors.
139
     * @return   array   the structure of the dir
140
     */
141
    protected static function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false)
142
    {
143
        $struct = array('dirs' => array(), 'files' => array());
144
        if (($dir = @opendir($sPath)) === false) {
145
            if (!$silent) {
146
                System::raiseError("Could not open dir $sPath");
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
147
            }
148
            return $struct; // XXX could not open error
149
        }
150
151
        $struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ?
152
        $list = array();
153
        while (false !== ($file = readdir($dir))) {
154
            if ($file != '.' && $file != '..') {
155
                $list[] = $file;
156
            }
157
        }
158
159
        closedir($dir);
160
        natsort($list);
161
        if ($aktinst < $maxinst || $maxinst == 0) {
162
            foreach ($list as $val) {
163
                $path = $sPath . DIRECTORY_SEPARATOR . $val;
164 View Code Duplication
                if (is_dir($path) && !is_link($path)) {
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...
165
                    $tmp    = System::_dirToStruct($path, $maxinst, $aktinst+1, $silent);
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
166
                    $struct = array_merge_recursive($struct, $tmp);
167
                } else {
168
                    $struct['files'][] = $path;
169
                }
170
            }
171
        }
172
173
        return $struct;
174
    }
175
176
    /**
177
     * Creates a nested array representing the structure of a directory and files
178
     *
179
     * @param    array $files Array listing files and dirs
180
     * @return   array
181
     * @static
182
     * @see System::_dirToStruct()
183
     */
184
    protected static function _multipleToStruct($files)
185
    {
186
        $struct = array('dirs' => array(), 'files' => array());
187
        settype($files, 'array');
188
        foreach ($files as $file) {
189 View Code Duplication
            if (is_dir($file) && !is_link($file)) {
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...
190
                $tmp    = System::_dirToStruct($file, 0);
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
191
                $struct = array_merge_recursive($tmp, $struct);
192
            } else {
193
                if (!in_array($file, $struct['files'])) {
194
                    $struct['files'][] = $file;
195
                }
196
            }
197
        }
198
        return $struct;
199
    }
200
201
    /**
202
     * The rm command for removing files.
203
     * Supports multiple files and dirs and also recursive deletes
204
     *
205
     * @param    string  $args   the arguments for rm
206
     * @return   mixed   PEAR_Error or true for success
207
     * @static
208
     * @access   public
209
     */
210
    public static function rm($args)
211
    {
212
        $opts = System::_parseArgs($args, 'rf'); // "f" does nothing but I like it :-)
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
213
        if (PEAR::isError($opts)) {
214
            return System::raiseError($opts);
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
215
        }
216
        foreach ($opts[0] as $opt) {
217
            if ($opt[0] == 'r') {
218
                $do_recursive = true;
219
            }
220
        }
221
        $ret = true;
222
        if (isset($do_recursive)) {
223
            $struct = System::_multipleToStruct($opts[1]);
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
224
            foreach ($struct['files'] as $file) {
225
                if (!@unlink($file)) {
226
                    $ret = false;
227
                }
228
            }
229
230
            rsort($struct['dirs']);
231
            foreach ($struct['dirs'] as $dir) {
232
                if (!@rmdir($dir)) {
233
                    $ret = false;
234
                }
235
            }
236
        } else {
237
            foreach ($opts[1] as $file) {
238
                $delete = (is_dir($file)) ? 'rmdir' : 'unlink';
239
                if (!@$delete($file)) {
240
                    $ret = false;
241
                }
242
            }
243
        }
244
        return $ret;
245
    }
246
247
    /**
248
     * Make directories.
249
     *
250
     * The -p option will create parent directories
251
     * @param    string  $args    the name of the director(y|ies) to create
252
     * @return   bool    True for success
253
     */
254
    public static function mkDir($args)
255
    {
256
        $opts = System::_parseArgs($args, 'pm:');
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
257
        if (PEAR::isError($opts)) {
258
            return System::raiseError($opts);
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
259
        }
260
261
        $mode = 0777; // default mode
262
        foreach ($opts[0] as $opt) {
263
            if ($opt[0] == 'p') {
264
                $create_parents = true;
265
            } elseif ($opt[0] == 'm') {
266
                // if the mode is clearly an octal number (starts with 0)
267
                // convert it to decimal
268
                if (strlen($opt[1]) && $opt[1]{0} == '0') {
269
                    $opt[1] = octdec($opt[1]);
270
                } else {
271
                    // convert to int
272
                    $opt[1] += 0;
273
                }
274
                $mode = $opt[1];
275
            }
276
        }
277
278
        $ret = true;
279
        if (isset($create_parents)) {
280
            foreach ($opts[1] as $dir) {
281
                $dirstack = array();
282
                while ((!file_exists($dir) || !is_dir($dir)) &&
283
                        $dir != DIRECTORY_SEPARATOR) {
284
                    array_unshift($dirstack, $dir);
285
                    $dir = dirname($dir);
286
                }
287
288
                while ($newdir = array_shift($dirstack)) {
289
                    if (!is_writeable(dirname($newdir))) {
290
                        $ret = false;
291
                        break;
292
                    }
293
294
                    if (!mkdir($newdir, $mode)) {
295
                        $ret = false;
296
                    }
297
                }
298
            }
299
        } else {
300
            foreach($opts[1] as $dir) {
301
                if ((@file_exists($dir) || !is_dir($dir)) && !mkdir($dir, $mode)) {
302
                    $ret = false;
303
                }
304
            }
305
        }
306
307
        return $ret;
308
    }
309
310
    /**
311
     * Concatenate files
312
     *
313
     * Usage:
314
     * 1) $var = System::cat('sample.txt test.txt');
315
     * 2) System::cat('sample.txt test.txt > final.txt');
316
     * 3) System::cat('sample.txt test.txt >> final.txt');
317
     *
318
     * Note: as the class use fopen, urls should work also (test that)
319
     *
320
     * @param    string  $args   the arguments
321
     * @return   boolean true on success
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean|null|string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
322
     */
323
    public static function &cat($args)
324
    {
325
        $ret = null;
326
        $files = array();
327
        if (!is_array($args)) {
328
            $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);
329
        }
330
331
        $count_args = count($args);
332
        for ($i = 0; $i < $count_args; $i++) {
333
            if ($args[$i] == '>') {
334
                $mode = 'wb';
335
                $outputfile = $args[$i+1];
336
                break;
337
            } elseif ($args[$i] == '>>') {
338
                $mode = 'ab+';
339
                $outputfile = $args[$i+1];
340
                break;
341
            } else {
342
                $files[] = $args[$i];
343
            }
344
        }
345
        $outputfd = false;
346
        if (isset($mode)) {
347
            if (!$outputfd = fopen($outputfile, $mode)) {
348
                $err = System::raiseError("Could not open $outputfile");
0 ignored issues
show
Bug introduced by
The variable $outputfile 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...
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
349
                return $err;
350
            }
351
            $ret = true;
352
        }
353
        foreach ($files as $file) {
354
            if (!$fd = fopen($file, 'r')) {
355
                System::raiseError("Could not open $file");
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
356
                continue;
357
            }
358
            while ($cont = fread($fd, 2048)) {
359
                if (is_resource($outputfd)) {
360
                    fwrite($outputfd, $cont);
361
                } else {
362
                    $ret .= $cont;
363
                }
364
            }
365
            fclose($fd);
366
        }
367
        if (is_resource($outputfd)) {
368
            fclose($outputfd);
369
        }
370
        return $ret;
371
    }
372
373
    /**
374
     * Creates temporary files or directories. This function will remove
375
     * the created files when the scripts finish its execution.
376
     *
377
     * Usage:
378
     *   1) $tempfile = System::mktemp("prefix");
379
     *   2) $tempdir  = System::mktemp("-d prefix");
380
     *   3) $tempfile = System::mktemp();
381
     *   4) $tempfile = System::mktemp("-t /var/tmp prefix");
382
     *
383
     * prefix -> The string that will be prepended to the temp name
384
     *           (defaults to "tmp").
385
     * -d     -> A temporary dir will be created instead of a file.
386
     * -t     -> The target dir where the temporary (file|dir) will be created. If
387
     *           this param is missing by default the env vars TMP on Windows or
388
     *           TMPDIR in Unix will be used. If these vars are also missing
389
     *           c:\windows\temp or /tmp will be used.
390
     *
391
     * @param   string  $args  The arguments
0 ignored issues
show
Documentation introduced by
Should the type for parameter $args not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
392
     * @return  mixed   the full path of the created (file|dir) or false
393
     * @see System::tmpdir()
394
     */
395
    public static function mktemp($args = null)
0 ignored issues
show
Coding Style introduced by
mktemp uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
396
    {
397
        static $first_time = true;
398
        $opts = System::_parseArgs($args, 't:d');
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
399
        if (PEAR::isError($opts)) {
400
            return System::raiseError($opts);
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
401
        }
402
403
        foreach ($opts[0] as $opt) {
404
            if ($opt[0] == 'd') {
405
                $tmp_is_dir = true;
406
            } elseif ($opt[0] == 't') {
407
                $tmpdir = $opt[1];
408
            }
409
        }
410
411
        $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp';
412
        if (!isset($tmpdir)) {
413
            $tmpdir = System::tmpdir();
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
414
        }
415
416
        if (!System::mkDir(array('-p', $tmpdir))) {
0 ignored issues
show
Documentation introduced by
array('-p', $tmpdir) is of type array<integer,?,{"0":"string","1":"?"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
417
            return false;
418
        }
419
420
        $tmp = tempnam($tmpdir, $prefix);
421
        if (isset($tmp_is_dir)) {
422
            unlink($tmp); // be careful possible race condition here
423
            if (!mkdir($tmp, 0700)) {
424
                return System::raiseError("Unable to create temporary directory $tmpdir");
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
425
            }
426
        }
427
428
        $GLOBALS['_System_temp_files'][] = $tmp;
429
        if (isset($tmp_is_dir)) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
430
            //$GLOBALS['_System_temp_files'][] = dirname($tmp);
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
431
        }
432
433
        if ($first_time) {
434
            PEAR::registerShutdownFunc(array('System', '_removeTmpFiles'));
435
            $first_time = false;
436
        }
437
438
        return $tmp;
439
    }
440
441
    /**
442
     * Remove temporary files created my mkTemp. This function is executed
443
     * at script shutdown time
444
     */
445
    public static function _removeTmpFiles()
0 ignored issues
show
Coding Style introduced by
_removeTmpFiles uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
446
    {
447
        if (count($GLOBALS['_System_temp_files'])) {
448
            $delete = $GLOBALS['_System_temp_files'];
449
            array_unshift($delete, '-r');
450
            System::rm($delete);
0 ignored issues
show
Documentation introduced by
$delete is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
451
            $GLOBALS['_System_temp_files'] = array();
452
        }
453
    }
454
455
    /**
456
     * Get the path of the temporal directory set in the system
457
     * by looking in its environments variables.
458
     * Note: php.ini-recommended removes the "E" from the variables_order setting,
459
     * making unavaible the $_ENV array, that s why we do tests with _ENV
460
     *
461
     * @return string The temporary directory on the system
462
     */
463
    public static function tmpdir()
0 ignored issues
show
Coding Style introduced by
tmpdir uses the super-global variable $_ENV which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
464
    {
465
        if (OS_WINDOWS) {
466 View Code Duplication
            if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) {
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...
467
                return $var;
468
            }
469 View Code Duplication
            if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) {
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...
470
                return $var;
471
            }
472 View Code Duplication
            if ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : getenv('USERPROFILE')) {
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...
473
                return $var;
474
            }
475 View Code Duplication
            if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) {
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...
476
                return $var;
477
            }
478
            return getenv('SystemRoot') . '\temp';
479
        }
480 View Code Duplication
        if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) {
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...
481
            return $var;
482
        }
483
        return realpath('/tmp');
484
    }
485
486
    /**
487
     * The "which" command (show the full path of a command)
488
     *
489
     * @param string $program The command to search for
490
     * @param mixed  $fallback Value to return if $program is not found
491
     *
492
     * @return mixed A string with the full path or false if not found
493
     * @author Stig Bakken <[email protected]>
494
     */
495
    public static function which($program, $fallback = false)
496
    {
497
        // enforce API
498
        if (!is_string($program) || '' == $program) {
499
            return $fallback;
500
        }
501
502
        // full path given
503
        if (basename($program) != $program) {
504
            $path_elements[] = dirname($program);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$path_elements was never initialized. Although not strictly required by PHP, it is generally a good practice to add $path_elements = 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...
505
            $program = basename($program);
506
        } else {
507
            $path = getenv('PATH');
508
            if (!$path) {
509
                $path = getenv('Path'); // some OSes are just stupid enough to do this
510
            }
511
512
            $path_elements = explode(PATH_SEPARATOR, $path);
513
        }
514
515
        if (OS_WINDOWS) {
516
            $exe_suffixes = getenv('PATHEXT')
517
                                ? explode(PATH_SEPARATOR, getenv('PATHEXT'))
518
                                : array('.exe','.bat','.cmd','.com');
519
            // allow passing a command.exe param
520
            if (strpos($program, '.') !== false) {
521
                array_unshift($exe_suffixes, '');
522
            }
523
        } else {
524
            $exe_suffixes = array('');
525
        }
526
527
        foreach ($exe_suffixes as $suff) {
528
            foreach ($path_elements as $dir) {
529
                $file = $dir . DIRECTORY_SEPARATOR . $program . $suff;
530
                if (is_executable($file)) {
531
                    return $file;
532
                }
533
            }
534
        }
535
        return $fallback;
536
    }
537
538
    /**
539
     * The "find" command
540
     *
541
     * Usage:
542
     *
543
     * System::find($dir);
544
     * System::find("$dir -type d");
545
     * System::find("$dir -type f");
546
     * System::find("$dir -name *.php");
547
     * System::find("$dir -name *.php -name *.htm*");
548
     * System::find("$dir -maxdepth 1");
549
     *
550
     * Params implemented:
551
     * $dir            -> Start the search at this directory
552
     * -type d         -> return only directories
553
     * -type f         -> return only files
554
     * -maxdepth <n>   -> max depth of recursion
555
     * -name <pattern> -> search pattern (bash style). Multiple -name param allowed
556
     *
557
     * @param  mixed Either array or string with the command line
558
     * @return array Array of found files
559
     */
560
    public static function find($args)
561
    {
562
        if (!is_array($args)) {
563
            $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);
564
        }
565
        $dir = realpath(array_shift($args));
566
        if (!$dir) {
567
            return array();
568
        }
569
        $patterns = array();
570
        $depth = 0;
571
        $do_files = $do_dirs = true;
572
        $args_count = count($args);
573
        for ($i = 0; $i < $args_count; $i++) {
574
            switch ($args[$i]) {
575
                case '-type':
576
                    if (in_array($args[$i+1], array('d', 'f'))) {
577
                        if ($args[$i+1] == 'd') {
578
                            $do_files = false;
579
                        } else {
580
                            $do_dirs = false;
581
                        }
582
                    }
583
                    $i++;
584
                    break;
585
                case '-name':
586
                    $name = preg_quote($args[$i+1], '#');
587
                    // our magic characters ? and * have just been escaped,
588
                    // so now we change the escaped versions to PCRE operators
589
                    $name = strtr($name, array('\?' => '.', '\*' => '.*'));
590
                    $patterns[] = '('.$name.')';
591
                    $i++;
592
                    break;
593
                case '-maxdepth':
594
                    $depth = $args[$i+1];
595
                    break;
596
            }
597
        }
598
        $path = System::_dirToStruct($dir, $depth, 0, true);
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
599
        if ($do_files && $do_dirs) {
600
            $files = array_merge($path['files'], $path['dirs']);
601
        } elseif ($do_dirs) {
602
            $files = $path['dirs'];
603
        } else {
604
            $files = $path['files'];
605
        }
606
        if (count($patterns)) {
607
            $dsq = preg_quote(DIRECTORY_SEPARATOR, '#');
608
            $pattern = '#(^|'.$dsq.')'.implode('|', $patterns).'($|'.$dsq.')#';
609
            $ret = array();
610
            $files_count = count($files);
611
            for ($i = 0; $i < $files_count; $i++) {
612
                // only search in the part of the file below the current directory
613
                $filepart = basename($files[$i]);
614
                if (preg_match($pattern, $filepart)) {
615
                    $ret[] = $files[$i];
616
                }
617
            }
618
            return $ret;
619
        }
620
        return $files;
621
    }
622
}