Passed
Push — master ( 1b90b9...7956e0 )
by Gabriel
03:50 queued 11s
created

Nip_File_System::formatSize()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 2
eloc 5
c 1
b 0
f 1
nc 2
nop 1
dl 0
loc 10
rs 10
1
<?php
2
3
use Nip\Filesystem\Exception\IOException;
4
5
/**
6
 * Class Nip_File_System
7
 */
8
class Nip_File_System
9
{
10
    protected $_uploadErrors = [
11
        0 => 'There is no error, the file uploaded with success',
12
        1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini',
13
        2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
14
        3 => 'The uploaded file was only partially uploaded',
15
        4 => 'No file was uploaded',
16
        6 => 'Missing a temporary folder',
17
    ];
18
19
    /**
20
     * Singleton.
21
     *
22
     * @return self
23
     */
24
    public static function instance()
25
    {
26
        static $instance;
27
        if (!($instance instanceof self)) {
28
            $instance = new self();
29
        }
30
31
        return $instance;
32
    }
33
34
    /**
35
     * Returns error message on upload, if any.
36
     *
37
     * @param string $file
38
     * @param array $extensions
39
     *
40
     * @return mixed
41
     */
42
    public function getUploadError($file, $extensions = [])
43
    {
44
        $messages = [
45
            'max_post' => 'POST exceeded maximum allowed size.',
46
            'no_upload' => 'No upload found in \$_FILES',
47
            'bad_upload' => 'Upload failed is_uploaded_file test.',
48
            'no_name' => 'File has no name.',
49
            'bad_extension' => 'Invalid file extension',
50
        ];
51
52
        $errorCode = $this->getUploadErrorNo($file, $extensions);
53
        if (is_int($errorCode)) {
54
            $translateSlug = 'general.errors.upload.code-'.$errorCode;
55
56
            return app('translator')->hasTranslation($translateSlug) ? __($translateSlug) : $this->_uploadErrors[$errorCode];
0 ignored issues
show
Bug introduced by
The function __ was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

56
            return app('translator')->hasTranslation($translateSlug) ? /** @scrutinizer ignore-call */ __($translateSlug) : $this->_uploadErrors[$errorCode];
Loading history...
Bug introduced by
The function app was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

56
            return /** @scrutinizer ignore-call */ app('translator')->hasTranslation($translateSlug) ? __($translateSlug) : $this->_uploadErrors[$errorCode];
Loading history...
57
        } elseif (is_string($errorCode)) {
58
            $translateSlug = 'general.errors.upload.'.$errorCode;
59
60
            return app('translator')->hasTranslation($translateSlug) ? __($translateSlug) : $messages[$errorCode];
61
        }
62
63
        return false;
64
    }
65
66
    /**
67
     * Returns error message on upload, if any.
68
     *
69
     * @param string $file
70
     * @param array $extensions
71
     *
72
     * @return mixed
73
     */
74
    public function getUploadErrorNo($file, $extensions = [])
75
    {
76
        $result = false;
77
78
        $maxUpload = ini_get('post_max_size');
79
        $unit = strtoupper(substr($maxUpload, -1));
80
        $multiplier = $unit == 'M' ? 1048576 : ($unit == 'K' ? 1024 : ($unit == 'G' ? 1073741824 : 1));
81
82
        if ($maxUpload && ((int)$_SERVER['CONTENT_LENGTH'] > $multiplier * (int)$maxUpload)) {
83
            $result = 'max_post';
84
        }
85
86
        if (!isset($file)) {
87
            $result = 'no_upload';
88
        } else {
89
            if (isset($file['error']) && $file['error'] != 0) {
90
                $result = $file['error'];
91
            } else {
92
                if (!isset($file['tmp_name']) || !@is_uploaded_file($file['tmp_name'])) {
93
                    $result = 'bad_upload';
94
                } else {
95
                    if (!isset($file['name'])) {
96
                        $result = 'no_name';
97
                    }
98
                }
99
            }
100
        }
101
102
        if ($extensions && !in_array($this->getExtension($file['name']), $extensions)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $extensions of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
103
            $result = 'bad_extension';
104
        }
105
106
        return $result;
107
    }
108
109
    /**
110
     * Get file extension.
111
     *
112
     * @param string $str
113
     *
114
     * @return string
115
     */
116
    public function getExtension($str)
117
    {
118
        return strtolower(pathinfo($str, PATHINFO_EXTENSION));
119
    }
120
121
    /**
122
     * Gets list of all files within a directory.
123
     *
124
     * @param string $dir
125
     * @param bool $recursive
126
     *
127
     * @return array
128
     */
129
    public function scanDirectory($dir, $recursive = false, $fullPaths = false)
130
    {
131
        $result = [];
132
133
        if (is_dir($dir)) {
134
            if ($recursive) {
135
                $iterator = new RecursiveDirectoryIterator($dir);
136
                foreach (new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::CHILD_FIRST) as $file) {
137
                    if ($file->isFile()) {
138
                        $result[] = ($fullPaths ? $file->getPath().DIRECTORY_SEPARATOR : '').$file->getFilename();
139
                    }
140
                }
141
            } else {
142
                $iterator = new DirectoryIterator($dir);
143
                foreach ($iterator as $file) {
144
                    if ($file->isFile()) {
145
                        $result[] = $file->getFilename();
146
                    }
147
                }
148
            }
149
        }
150
151
        return $result;
152
    }
153
154
    /**
155
     * Recursively create a directory and set it's permissions.
156
     *
157
     * @param string $dir
158
     * @param int $mode
159
     *
160
     * @return bool
161
     */
162
    public function createDirectory($dir, $mode = 0777)
163
    {
164
        return is_dir($dir) ? true : mkdir($dir, $mode, true);
165
    }
166
167
    /**
168
     * Builds array-tree of directory, with files as final nodes.
169
     *
170
     * @param string $dir
171
     * @param array $tree
172
     *
173
     * @return array
174
     */
175
    public function directoryTree($dir, $tree = [])
176
    {
177
        $dir = realpath($dir);
178
        $d = dir($dir);
179
180
        while (false != ($entry = $d->read())) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $entry = $d->read() of type string to the boolean false. If you are specifically checking for a non-empty string, consider using the more explicit !== '' instead.
Loading history...
181
            $complete = $d->path.'/'.$entry;
182
            if (!in_array($entry, ['.', '..', '.svn'])) {
183
                if (is_dir($complete)) {
184
                    $tree[$entry] = $this->directoryTree($complete, $tree[$dir][$entry]);
185
                } else {
186
                    $tree[] = $entry;
187
                }
188
            }
189
        }
190
191
        $d->close();
192
193
        return $tree;
194
    }
195
196
    /**
197
     * Recursively empties a directory.
198
     *
199
     * @param string $dir
200
     */
201
    public function emptyDirectory($dir)
202
    {
203
        $dir = rtrim($dir, '/');
204
205
        $files = scandir($dir);
206
207
        array_shift($files);
0 ignored issues
show
Bug introduced by
It seems like $files can also be of type false; however, parameter $array of array_shift() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

207
        array_shift(/** @scrutinizer ignore-type */ $files);
Loading history...
208
        array_shift($files);
209
210
        foreach ($files as $file) {
211
            $file = $dir.'/'.$file;
212
            if (is_dir($file)) {
213
                $this->removeDirectory($file);
214
            } else {
215
                unlink($file);
216
            }
217
        }
218
219
        return $this;
220
    }
221
222
    /**
223
     * Recursively removes a directory.
224
     *
225
     * @param string $dir
226
     */
227
    public function removeDirectory($dir)
228
    {
229
        $dir = rtrim($dir, '/');
230
231
        if (is_dir($dir)) {
232
            $files = scandir($dir);
233
234
            foreach ($files as $file) {
235
                if (!in_array($file, ['.', '..'])) {
236
                    $file = $dir.DIRECTORY_SEPARATOR.$file;
237
                    if (is_dir($file)) {
238
                        $this->removeDirectory($file);
239
                    } else {
240
                        unlink($file);
241
                    }
242
                }
243
            }
244
245
            rmdir($dir);
246
        }
247
    }
248
249
    public function deleteFile($path)
250
    {
251
        if (file_exists($path)) {
252
            unlink($path);
253
        }
254
255
        return $this;
256
    }
257
258
    /**
259
     * @param $source
260
     * @param $destination
261
     * @return mixed
262
     */
263
    public function copyDirectory($source, $destination)
264
    {
265
        if (!is_dir($destination)) {
266
            mkdir($destination, 0755, true);
267
        }
268
        $process = new Nip_Process("cp -R -f $source/* $destination");
0 ignored issues
show
Bug introduced by
The type Nip_Process was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
269
270
        return $process->run();
271
    }
272
273
    /**
274
     * @param $bytes
275
     * @return string
276
     */
277
    public function formatSize($bytes)
278
    {
279
        if (!$bytes) {
280
            return '0 kb';
281
        }
282
283
        $s = ['b', 'kb', 'MB', 'GB', 'TB', 'PB'];
284
        $e = floor(log($bytes) / log(1024));
285
286
        return sprintf('%.2f '.$s[$e], ($bytes / pow(1024, floor($e))));
287
    }
288
289
    /**
290
     * @param $file
291
     * @param $mode
292
     */
293
    public function chmod($file, $mode)
294
    {
295
        if (true !== @chmod($file, $mode)) {
296
            throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file);
297
        }
298
    }
299
}
300