FS::__clone()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 0
dl 0
loc 2
ccs 0
cts 1
cp 0
rs 10
c 1
b 0
f 0
cc 1
nc 1
nop 0
crap 2
1
<?php namespace Helpers;
2
3
/**
4
 * Class FS
5
 * @package Helpers
6
 */
7
class FS
8
{
9
    /**
10
     * @var FS cached reference to singleton instance
11
     */
12
    protected static $instance;
13
14
    /**
15
     * @var array
16
     */
17
    private $_fileInfo = array();
18
19
    /**
20
     * gets the instance via lazy initialization (created on first usage)
21
     *
22
     * @return self
23
     */
24 70
    public static function getInstance()
25
    {
26 70
        if (null === self::$instance) {
27 1
            self::$instance = new self();
28 1
        }
29
30 70
        return self::$instance;
31
    }
32
33
    /**
34
     * is not allowed to call from outside: private!
35
     *
36
     */
37 1
    private function __construct()
38
    {
39 1
    }
40
41
    /**
42
     * prevent the instance from being cloned
43
     *
44
     * @return void
45
     */
46
    private function __clone()
47
    {
48
    }
49
50
    /**
51
     * prevent from being unserialized
52
     *
53
     * @return void
54
     */
55
    public function __wakeup()
56
    {
57
    }
58
59
    /**
60
     * Чтобы не дергать постоянно файл который обрабатываем
61
     *
62
     * @access private
63
     * @param string $file ключ
64
     * @return string информация из pathinfo о обрабатываемом файле input
65
     */
66
    private function _pathinfo($file, $mode)
67
    {
68
        if (!is_scalar($file) && !is_scalar($mode)) {
0 ignored issues
show
introduced by
The condition is_scalar($file) is always true.
Loading history...
Coding Style introduced by
Expected 1 space after NOT operator; 0 found
Loading history...
69
            $file = $mode = '';
70
        }
71
        $flag = !(empty($file) || empty($mode));
0 ignored issues
show
Coding Style introduced by
Expected 1 space after NOT operator; 0 found
Loading history...
72
        $f = MODX_BASE_PATH . $this->relativePath($file);
73
        if ($flag && !isset($this->_fileInfo[$f], $this->_fileInfo[$f][$mode])) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after NOT operator; 0 found
Loading history...
74
            $this->_fileInfo[$f] = pathinfo($f);
75
        }
76
        $out = $flag && isset($this->_fileInfo[$f][$mode]) ? $this->_fileInfo[$f][$mode] : '';
77
78
        return $out;
79
    }
80
81
    /**
82
     * @param $file
83
     * @return string
84
     */
85
    public function takeFileDir($file)
86
    {
87
        return $this->_pathinfo($file, 'dirname');
88
    }
89
90
    /**
91
     * @param $file
92
     * @return string
93
     */
94
    public function takeFileBasename($file)
95
    { //file name with extension
0 ignored issues
show
Coding Style introduced by
Opening brace must be the last content on the line
Loading history...
96
        return $this->_pathinfo($file, 'basename');
97
    }
98
99
    /**
100
     * @param $file
101
     * @return string
102
     */
103
    public function takeFileName($file)
104
    {
105
        return $this->_pathinfo($file, 'filename');
106
    }
107
108
    /**
109
     * @param $file
110
     * @param bool $lower
111
     * @return string
112
     */
113
    public function takeFileExt($file, $lower = true)
114
    {
115
        $str = $this->_pathinfo($file, 'extension');
116
        if($lower){
0 ignored issues
show
Coding Style introduced by
Expected 1 space after IF keyword; 0 found
Loading history...
117
            $str = strtolower($str);
118
        }
119
        return $str;
120
    }
121
122
    /**
123
     * @param $file
124
     * @return bool
125
     */
126
    public function checkFile($file)
127
    {
128
        $f = is_scalar($file) ? MODX_BASE_PATH . $this->relativePath($file) : '';
129
130
        return (! empty($f) && is_file($f) && is_readable($f));
131
    }
132
133
    /**
134
     * @param $path
135
     * @return bool
136
     */
137
    public function checkDir($path)
138
    {
139
        $f = is_scalar($path) ? $this->relativePath($path) : '';
140
141
        return (! empty($f) && is_dir(MODX_BASE_PATH . $f) && is_readable(MODX_BASE_PATH . $f));
142
    }
143
144
    /**
145
     * @param $file
146
     * @param bool|array $format
147
     * @return int|string
148
     */
149
    public function fileSize($file, $format = false)
150
    {
151
        $out = 0;
152
        if ($this->checkFile($file)) {
153
            $out = filesize(MODX_BASE_PATH . $this->relativePath($file));
154
        }
155
156
        if($format === true) $format = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
0 ignored issues
show
Coding Style introduced by
Expected 1 space after IF keyword; 0 found
Loading history...
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
157
        if (is_array($format)) {
158
            $size = $out > 0 ? floor(log($out, 1024)) : 0;
159
            $type = isset($format[$size]) ? ' '.$format[$size] : '';
0 ignored issues
show
Coding Style introduced by
Concat operator must be surrounded by a single space
Loading history...
160
            $out = number_format($out / pow(1024, $size), 2, '.', ',') . $type;
161
        }
162
163
        return $out;
164
    }
165
166
    /**
167
     * Если класс finfo и функция mime_content_type не доступны, то происходит сверка типов:
168
     *      - image/jpeg
169
     *      - image/png
170
     *      - image/gif
171
     * Для всех остальных файлов будет присвоен тип application/octet-stream
172
     *
173
     * @param string $file Имя файла
174
     * @return null|string MIME тип файла
175
     */
176
    public function takeFileMIME($file)
0 ignored issues
show
Coding Style introduced by
Function's nesting level (6) exceeds 3; consider refactoring the function
Loading history...
Coding Style introduced by
This method is not in camel caps format.

This check looks for method names that are not written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection seeker becomes databaseConnectionSeeker.

Loading history...
177
    {
178
        $out = null;
179
        $path = $this->relativePath($file);
180
        if ($this->checkFile($path)) {
181
            $fname = MODX_BASE_PATH . $path;
182
            switch (true) {
183
                /** need fileinfo extension */
184
                case (extension_loaded('fileinfo') && class_exists('\finfo')):
185
                    $fi = new \finfo(FILEINFO_MIME_TYPE);
186
                    if ($fi) {
0 ignored issues
show
introduced by
$fi is of type finfo, thus it always evaluated to true.
Loading history...
187
                        $out = $fi->file($fname);
188
                    }
189
                    break;
190
                case function_exists('mime_content_type'):
191
                    list($out) = explode(';', @mime_content_type($fname));
0 ignored issues
show
Bug introduced by
It seems like @mime_content_type($fname) can also be of type false; however, parameter $string of explode() does only seem to accept string, 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

191
                    list($out) = explode(';', /** @scrutinizer ignore-type */ @mime_content_type($fname));
Loading history...
192
                    break;
193
                default:
194
                    /**
195
                     * @see: http://www.php.net/manual/ru/function.finfo-open.php#112617
196
                     */
197
                    $fh = fopen($fname, 'rb');
198
                    if ($fh) {
0 ignored issues
show
introduced by
$fh is of type resource, thus it always evaluated to false.
Loading history...
199
                        $bytes6 = fread($fh, 6);
200
                        fclose($fh);
201
                        switch (true) {
202
                            case ($bytes6 === false):
203
                                break;
204
                            case (substr($bytes6, 0, 3) == "\xff\xd8\xff"):
205
                                $out = 'image/jpeg';
206
                                break;
207
                            case ($bytes6 == "\x89PNG\x0d\x0a"):
208
                                $out = 'image/png';
209
                                break;
210
                            case ($bytes6 == "GIF87a" || $bytes6 == "GIF89a"):
211
                                $out = 'image/gif';
212
                                break;
213
                            default:
214
                                $out = 'application/octet-stream';
215
                                break;
216
                        }
217
                    }
218
            }
219
        }
220
221
        return $out;
222
    }
223
224
    /**
225
     * @param $path
226
     * @param int $perm
227
     * @return bool
228
     */
229
    public function makeDir($path, $perm = 0755)
230
    {
231
        if (! $this->checkDir($path)) {
232
            $path = MODX_BASE_PATH . $this->relativePath($path);
233
            $flag = mkdir($path, $this->toOct($perm), true);
234
        } else {
235
            $flag = true;
236
        }
237
238
        return $flag;
239
    }
240
241
    /**
242
     * Копирование файла с проверкой на существование оригинального файла и созданием папок
243
     *
244
     * @param string $from источник
245
     * @param string $to получатель
246
     * @return bool статус копирования
247
     */
248
    public function copyFile($from, $to, $chmod = 0644)
249
    {
250
        $flag = false;
251
        $from = MODX_BASE_PATH . $this->relativePath($from);
252
        $to = MODX_BASE_PATH . $this->relativePath($to);
253
        $dir = $this->takeFileDir($to);
254
        if ($this->checkFile($from) && $this->makeDir($dir) && copy($from, $to)) {
255
            chmod($to, $this->toOct($chmod));
256
            $flag = true;
257
        }
258
259
        return $flag;
260
    }
261
262
    /**
263
     * Перемещение файла с проверкой на существование оригинального файла и созданием папок
264
     *
265
     * @param string $from источник
266
     * @param string $to получатель
267
     * @return bool статус перемещения
268
     */
269
    public function moveFile($from, $to, $chmod = 0644)
270
    {
271
        $flag = false;
272
        $from = MODX_BASE_PATH . $this->relativePath($from);
273
        $to = MODX_BASE_PATH . $this->relativePath($to);
274
        $dir = $this->takeFileDir($to);
275
        if ($this->checkFile($from) && $this->makeDir($dir) && rename($from, $to)) {
276
            chmod($to, $this->toOct($chmod));
277
            $flag = true;
278
        }
279
280
        return $flag;
281
    }
282
283
    /**
284
     * Получение относительного пути к файлу или папки
285
     *
286
     * @param string $path путь из которого нужно получить относительный
287
     * @param string $owner начальный путь который стоит вырезать
288
     * @return string относительный путь
289
     */
290
    public function relativePath($path, $owner = null)
291
    {
292
        if (is_null($owner)) {
293
            $owner = MODX_BASE_PATH;
294
        }
295
        $path = str_replace('\\', '/', $path);
296
        if (!(empty($path) || !is_scalar($path)) && !preg_match("/^http(s)?:\/\/\w+/", $path)) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after NOT operator; 0 found
Loading history...
297
            $path = trim(preg_replace("#^" . preg_quote($owner) . "#", '', $path), DIRECTORY_SEPARATOR);
298
        } else {
299
            $path = '';
300
        }
301
302
        return $path;
303
    }
304
305
    /**
306
     * Перевод строки/числа из восьмеричной/десятичной системы счисления в 8-ричную систему счисления
307
     * Если параметр является числом, то он остается без изменений. Обработка применяется только к строкам.
308
     *
309
     * 755 => 755
310
     * 0755 => 493
311
     * '0755' => 493
312
     * '755' => 493
313
     *
314
     * @param  mixed $chmod строка или число в восьмеричной/десятичной системе счисления
315
     * @return int        число в восьмеричной системе счисления
316
     */
317 12
    public function toOct($chmod)
318
    {
319 12
        return is_string($chmod) ? octdec($chmod) : $chmod;
320
    }
321
322
    /**
323
     * @param $dirPath
324
     * @return bool
325
     */
326
    public function rmDir($dirPath)
327
    {
328
        $flag = false;
329
        $path = $_path = MODX_BASE_PATH . $this->relativePath($dirPath);
330
        if ($this->checkDir($path)) {
331
            $dirIterator = new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS);
332
            $dirRecursiveIterator = new \RecursiveIteratorIterator($dirIterator,
333
                \RecursiveIteratorIterator::CHILD_FIRST);
334
            foreach ($dirRecursiveIterator as $path) {
335
                $path->isDir() ? rmdir($path->getPathname()) : unlink($path->getPathname());
336
            }
337
            $flag = rmdir($_path);
338
        }
339
340
        return $flag;
341
    }
342
343
    /**
344
     * @param $file
345
     * @return bool
346
     */
347
    public function unlink($file)
348
    {
349
        $flag = false;
350
        if ($this->checkFile($file)) {
351
            $flag = unlink(MODX_BASE_PATH . $this->relativePath($file));
352
        }
353
354
        return $flag;
355
    }
356
357
    /**
358
     * @param $path
359
     * @return bool
360
     */
361
    public function delete($path)
362
    {
363
        $path = MODX_BASE_PATH . $this->relativePath($path);
364
        switch (true) {
365
            case $this->checkDir($path):
366
                $flag = $this->rmDir($path);
367
                break;
368
            case $this->checkFile($path):
369
                $flag = $this->unlink($path);
370
                break;
371
            default:
372
                $flag = false;
373
        }
374
375
        return $flag;
376
    }
377
378
    /**
379
     * @param $file
380
     * @param bool $full
381
     * @return string
382
     */
383
    public function getInexistantFilename($file, $full = false)
384
    {
385
        $i = 1;
386
        $file = $mainFile = MODX_BASE_PATH . $this->relativePath($file);
387
        while ($this->checkFile($file)) {
388
            $i++;
389
            $out = $this->takeFileDir($file) . '/';
390
            $out .= $this->takeFileName($mainFile) . "({$i})." . $this->takeFileExt($file);
391
            $file = $out;
392
        }
393
394
        return $full ? $file : $this->takeFileBasename($file);
395
    }
396
}
397