GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Branch dev (9a5b0a)
by t
02:19
created

LocalFile::getRealpath()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 2
eloc 4
c 1
b 1
f 0
nc 2
nop 1
dl 0
loc 6
ccs 5
cts 5
cp 1
crap 2
rs 10
1
<?php
2
/**
3
 * Class LocalFile
4
 *
5
 * @link https://www.icy2003.com/
6
 * @author icy2003 <[email protected]>
7
 * @copyright Copyright (c) 2019, icy2003
8
 */
9
namespace icy2003\php\icomponents\file;
10
11
use Exception;
12
use icy2003\php\C;
13
use icy2003\php\I;
14
use icy2003\php\icomponents\file\FileInterface;
15
use icy2003\php\ihelpers\Arrays;
16
use icy2003\php\ihelpers\Console;
17
use icy2003\php\ihelpers\Header;
18
use icy2003\php\ihelpers\Request;
19
use icy2003\php\ihelpers\Strings;
20
21
/**
22
 * 本地文件
23
 *
24
 * - 支持本地文件操作
25
 * - 支持网络文件部分属性:文件是否存在、文件大小
26
 */
27
class LocalFile extends Base implements FileInterface
28
{
29
30
    /**
31
     * 配置
32
     *
33
     * @var array
34
     */
35
    protected $_c = [
36
        'loader' => 'curl',
37
        'locale' => 'zh_CN.UTF-8',
38
        'buffer' => 4096,
39
        'mode' => 'rb',
40
        'rtrim' => true,
41
    ];
42
43
    /**
44
     * 文件属性
45
     *
46
     * - 文件名为键,属性为值
47
     *
48
     * @var array
49
     */
50
    protected $_attributes = [];
51
52
    /**
53
     * 初始化
54
     *
55
     * @param array $options 配置
56
     *      - locale:地区,默认 zh_CN.UTF-8
57
     *      - buffer:以字节方式读写时每段的字节长度,默认为 4096,即 4kb
58
     *      - mode:指定了所要求到该流的访问类型,默认 rb @link https://www.php.net/manual/zh/function.fopen.php
59
     *      - rtrim:在遍历行时是否去除行尾空白,默认 true,即去除
60
     *      - loader:读取远程资源时用的方法,默认为 curl(当其他方法无法读取时也会设置为 curl),支持值:curl、fopen、fsockopen
61
     *          - curl:使用 curl 获取远程文件信息
62
     *          - fopen:需要手动开启 allow_url_fopen 才能使用,不建议开启
63
     *          - fsockopen:使用 fsockopen 发送头获取信息
64
     * @return void
65
     */
66 36
    public function __construct($options = [])
67
    {
68 36
        $this->_c = Arrays::merge($this->_c, $options);
69 36
        setlocale(LC_ALL, (string) I::get($this->_c, 'locale', 'zh_CN.UTF-8'));
70 36
        clearstatcache();
71 36
    }
72
73
    /**
74
     * 获取 Hash 值
75
     *
76
     * @param string $fileName
77
     *
78
     * @return string
79
     */
80 17
    private function __hash($fileName)
81
    {
82 17
        return md5($fileName);
83
    }
84
85
    /**
86
     * 以别名返回路径
87
     *
88
     * @param string $file
89
     *
90
     * @return string
91
     */
92 34
    private function __file($file)
93
    {
94 34
        return (string) I::getAlias($file);
95
    }
96
97
    /**
98
     * 加载一个文件,本地(支持别名)或网络文件
99
     *
100
     * @param string $fileName
101
     *
102
     * @return static
103
     */
104 17
    protected function _load($fileName)
105
    {
106 17
        $fileName = $this->getRealpath($fileName);
107 17
        $hashName = $this->__hash($fileName);
108 17
        $this->_attributes[$hashName] = I::get($this->_attributes, $hashName, [
109 17
            'file' => $fileName,
110
            'isCached' => false,
111
            'isLocal' => true,
112
            // 以下属性需要重新设置
113
            'isExists' => false,
114 17
            'fileSize' => 0,
115
            'spl' => null,
116
            'splInfo' => null,
117
        ]);
118 17
        null === $this->_attributes[$hashName]['splInfo'] && $this->_attributes[$hashName]['splInfo'] = new \SplFileInfo($fileName);
119
        try {
120 17
            $splInfo = $this->_attributes[$hashName]['splInfo'];
121 17
            if (true !== $splInfo->isDir()) {
122 17
                null === $this->_attributes[$hashName]['spl'] && $this->_attributes[$hashName]['spl'] = new \SplFileObject($fileName, $this->_c['mode']);
123
            }
124 7
        } catch (Exception $e) {
125
            // 报错了也得继续跑,如果跑完一次 spl 和 splInfo 属性还是 null,在调用它们的时候自然会报错
126 7
            $this->_c['error'] = $e->getMessage();
127
            // 尝试用 curl 获取
128 7
            $this->_c['loader'] = 'curl';
129
        }
130
        // 如果已经被缓存了,直接返回
131 17
        if (true === $this->_attributes[$hashName]['isCached']) {
132 4
            return $this;
133
        }
134
        // 加上缓存标记
135 17
        $this->_attributes[$hashName]['isCached'] = true;
136 17
        if (preg_match('/^https?:\/\//', $fileName)) {
137 2
            $this->_attributes[$hashName]['isLocal'] = false;
138
            // 加载网络文件
139 2
            if ('curl' === $this->_c['loader'] && extension_loaded('curl')) {
140 2
                $curl = curl_init($fileName);
141 2
                if (is_resource($curl)) {
142 2
                    curl_setopt($curl, CURLOPT_NOBODY, true);
143 2
                    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
144 2
                    curl_setopt($curl, CURLOPT_HEADER, true);
145
                    // 公用名(Common Name)一般来讲就是填写你将要申请SSL证书的域名 (domain)或子域名(sub domain)
146
                    // - 设置为 1 是检查服务器SSL证书中是否存在一个公用名(common name)
147
                    // - 设置成 2,会检查公用名是否存在,并且是否与提供的主机名匹配
148
                    // - 0 为不检查名称。 在生产环境中,这个值应该是 2(默认值)
149 2
                    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
150
                    // 禁止 cURL 验证对等证书(peer's certificate)。要验证的交换证书可以在 CURLOPT_CAINFO 选项中设置
151 2
                    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
152 2
                    $result = curl_exec($curl);
153 2
                    if ($result && $info = curl_getinfo($curl)) {
154 2
                        if (200 == $info['http_code']) {
155 2
                            $this->_attributes[$hashName]['isExists'] = true;
156 2
                            $this->_attributes[$hashName]['fileSize'] = (int) $info['download_content_length'];
157
                        }
158
                    }
159 2
                    curl_close($curl);
160
                }
161 2
                return $this;
162
            }
163 1
            if ('fsockopen' === $this->_c['loader']) {
164 1
                $url = parse_url($fileName);
165 1
                $host = $url['host'];
166 1
                $path = (string) I::get($url, 'path', '/');
167 1
                $port = (int) I::get($url, 'port', 80);
168 1
                $fp = fsockopen($host, $port);
169 1
                if (is_resource($fp)) {
170 1
                    fputs($fp, "GET {$path} HTTP/1.1\r\n");
171 1
                    fputs($fp, "Host: {$host}:{$port}\r\n");
172 1
                    fputs($fp, "Connection: Close\r\n\r\n");
173 1
                    while (!feof($fp)) {
174 1
                        $line = fgets($fp);
175 1
                        preg_match('/HTTP.*(\s\d{3}\s)/', $line, $arr) && $this->_attributes[$hashName]['isExists'] = true;
176 1
                        preg_match('/Content-Length:(.*)/si', $line, $arr) && $this->_attributes[$hashName]['fileSize'] = (int) trim($arr[1]);
177
                    }
178 1
                    fclose($fp);
179
                }
180 1
                return $this;
181
            }
182 1
            if ('fopen' === $this->_c['loader'] && (bool) ini_get('allow_url_fopen')) {
183 1
                $headArray = (array) get_headers($fileName, 1);
184 1
                if (preg_match('/200/', $headArray[0])) {
185 1
                    $this->_attributes[$hashName]['isExists'] = true;
186 1
                    $this->_attributes[$hashName]['fileSize'] = (int) $headArray['Content-Length'];
187
                }
188 1
                return $this;
189
            }
190
        } else {
191 17
            $this->_attributes[$hashName]['isLocal'] = true;
192 17
            $this->_attributes[$hashName]['isExists'] = file_exists($fileName);
193 17
            if ($this->_attributes[$hashName]['isExists']) {
194 15
                $this->_attributes[$hashName]['fileSize'] = filesize($fileName);
195
            }
196 17
            $this->chmod($fileName, 0777, FileConstants::RECURSIVE_DISABLED);
197
        }
198 17
        return $this;
199
    }
200
201
    /**
202
     * 获取文件的属性
203
     *
204
     * @param string $fileName
205
     * @param string $name
206
     *
207
     * @return mixed
208
     */
209 17
    public function attribute($fileName, $name)
210
    {
211 17
        $this->_load($fileName);
212 17
        return I::get($this->_attributes, $this->__hash($this->getRealpath($fileName)) . '.' . $name);
213
    }
214
215
    /**
216
     * 获取文件对象
217
     *
218
     * @param string $fileName
219
     * @param string $mode 读写的模式,默认 rb
220
     *
221
     * @return \SplFileObject|null
222
     * @throws Exception
223
     */
224 6
    public function spl($fileName, $mode = 'rb')
225
    {
226 6
        $this->_c['mode'] = $mode;
227 6
        $spl = $this->attribute($fileName, 'spl');
228 6
        C::assertTrue($spl instanceof \SplFileObject, '文件打开失败:' . $fileName);
229 4
        return $spl;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $spl also could return the type false|string which is incompatible with the documented return type SplFileObject|null.
Loading history...
230
    }
231
232
    /**
233
     * 获取文件信息对象
234
     *
235
     * @param string $fileName
236
     *
237
     * @return \SplFileInfo
238
     */
239 1
    public function splInfo($fileName)
240
    {
241 1
        $splInfo = $this->attribute($fileName, 'splInfo');
242 1
        return $splInfo;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $splInfo also could return the type false|string which is incompatible with the documented return type SplFileInfo.
Loading history...
243
    }
244
245
    /**
246
     * 遍历行的生成器
247
     *
248
     * - 自动关闭后再次调用需要重新读取文件,不建议自动关闭
249
     *
250
     * @param string $fileName
251
     * @param boolean $autoClose 是否自动关闭文件,默认 false
252
     *
253
     * @return \Generator
254
     */
255 2
    public function linesGenerator($fileName, $autoClose = false)
256
    {
257
        try {
258 2
            $spl = $this->spl($fileName, 'r');
259 2
            while (false === $spl->eof() && ($line = $spl->fgets())) {
260 2
                true === $this->_c['rtrim'] && $line = rtrim($line);
261 2
                yield $line;
262
            }
263 2
        } finally {
264 2
            true === $autoClose && $this->close($fileName);
265
        }
266 2
    }
267
268
    /**
269
     * 返回文本的某行
270
     *
271
     * - 每取一行,文件指针会回到初始位置,如果需要大量的行,请直接使用 linesGenerator
272
     * - 自动关闭后再次调用需要重新读取文件,不建议自动关闭
273
     *
274
     * @param string $fileName
275
     * @param integer $lineNumber 行号
276
     * @param boolean $autoClose 是否自动关闭文件,默认 false
277
     *
278
     * @return string|null
279
     */
280 1
    public function line($fileName, $lineNumber = 0, $autoClose = false)
281
    {
282 1
        $spl = $this->spl($fileName, 'r');
283 1
        $lineNumber = (int) $lineNumber;
284 1
        foreach ($this->linesGenerator($fileName, $autoClose) as $k => $line) {
285 1
            if ($k === $lineNumber) {
286 1
                $spl->rewind();
287 1
                return $line;
288
            }
289
        }
290 1
        return null;
291
    }
292
293
    /**
294
     * 遍历字节的生成器
295
     *
296
     * - 自动关闭后再次调用需要重新读取文件,不建议自动关闭
297
     *
298
     * @param string $fileName
299
     * @param boolean $autoClose 是否自动关闭文件,默认 false
300
     * @param integer|null $buffer 每次读取的字节数,默认 null,值等于初始化时的 buffer 选项
301
     *
302
     * @return \Generator
303
     */
304 1
    public function dataGenerator($fileName, $autoClose = false, $buffer = null)
305
    {
306 1
        $bufferSize = 0;
307 1
        null === $buffer && $buffer = $this->_c['buffer'];
308
        try {
309 1
            $spl = $this->spl($fileName, 'rb');
310 1
            $size = $this->getFilesize($fileName);
311 1
            while (!$spl->eof() && $size > $bufferSize) {
312 1
                $bufferSize += $buffer;
313 1
                yield $spl->fread($bufferSize);
314
            }
315 1
        } finally {
316 1
            true === $autoClose && $this->close($fileName);
317
        }
318 1
    }
319
320
    /**
321
     * @ignore
322
     */
323 1
    public function getATime($fileName)
324
    {
325 1
        return fileatime($this->__file($fileName));
326
    }
327
328
    /**
329
     * @ignore
330
     */
331 2
    public function getBasename($file, $suffix = null)
332
    {
333 2
        return parent::getBasename($this->__file($file), $suffix);
334
    }
335
336
    /**
337
     * @ignore
338
     */
339 1
    public function getCTime($fileName)
340
    {
341 1
        return filectime($this->__file($fileName));
342
    }
343
344
    /**
345
     * @ignore
346
     */
347 1
    public function getExtension($fileName)
348
    {
349 1
        return pathinfo($this->__file($fileName), PATHINFO_EXTENSION);
350
    }
351
352
    /**
353
     * @ignore
354
     */
355 1
    public function getFilename($fileName)
356
    {
357 1
        return pathinfo($this->__file($fileName), PATHINFO_FILENAME);
358
    }
359
360
    /**
361
     * @ignore
362
     */
363 1
    public function getMtime($fileName)
364
    {
365 1
        return filemtime($this->__file($fileName));
366
    }
367
368
    /**
369
     * @ignore
370
     */
371 5
    public function getDirname($path)
372
    {
373 5
        return parent::getDirname($this->__file($path));
374
    }
375
376
    /**
377
     * @ignore
378
     */
379 1
    public function getPerms($path)
380
    {
381 1
        return fileperms($this->__file($path));
382
    }
383
384
    /**
385
     * @ignore
386
     */
387 3
    public function getFilesize($fileName)
388
    {
389 3
        return (int) $this->attribute($fileName, 'fileSize');
390
    }
391
392
    /**
393
     * @ignore
394
     */
395 1
    public function getType($path)
396
    {
397 1
        return filetype($this->__file($path));
398
    }
399
400
    /**
401
     * @ignore
402
     */
403 19
    public function isDir($dir)
404
    {
405 19
        return is_dir($this->__file($dir));
406
    }
407
408
    /**
409
     * @ignore
410
     */
411 1
    public function isDot($dir)
412
    {
413 1
        return in_array($this->getBasename($dir), ['.', '..']);
414
    }
415
416
    /**
417
     * @ignore
418
     */
419 10
    public function isFile($file)
420
    {
421 10
        $isLocal = $this->attribute($file, 'isLocal');
422 10
        if (true === $isLocal) {
423 10
            return is_file($this->__file($file));
424
        } else {
425 1
            return (bool) $this->attribute($file, 'isExists');
426
        }
427
    }
428
429
    /**
430
     * @ignore
431
     */
432 1
    public function isLink($link)
433
    {
434 1
        return is_link($this->__file($link));
435
    }
436
437
    /**
438
     * @ignore
439
     */
440 1
    public function isReadable($path)
441
    {
442 1
        return is_readable($this->__file($path));
443
    }
444
445
    /**
446
     * @ignore
447
     */
448 1
    public function isWritable($path)
449
    {
450 1
        return is_writable($this->__file($path));
451
    }
452
453
    /**
454
     * @ignore
455
     */
456 1
    public function getCommandResult($command)
457
    {
458 1
        return Console::exec($command);
459
    }
460
461
    /**
462
     * @ignore
463
     */
464 18
    public function getRealpath($path)
465
    {
466 18
        $path = $this->__file($path);
467 18
        $realPath = realpath($path);
468 18
        false === $realPath && $realPath = parent::getRealpath($path);
469 18
        return Strings::replace($realPath, ["\\" => '/']);
470
    }
471
472
    /**
473
     * @ignore
474
     */
475 3
    public function getLists($dir = null, $flags = FileConstants::COMPLETE_PATH | FileConstants::RECURSIVE_DISABLED)
476
    {
477 3
        null === $dir && $dir = $this->getRealpath('./');
478 3
        $dir = rtrim($this->__file($dir), '/') . '/';
479 3
        $iterator = new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS);
480 3
        if (I::hasFlag($flags, FileConstants::RECURSIVE)) {
481 3
            $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST);
482
        }
483 3
        $files = [];
484
        /**
485
         * @var \RecursiveDirectoryIterator $file
486
         */
487 3
        foreach ($iterator as $file) {
488 3
            if (I::hasFlag($flags, FileConstants::COMPLETE_PATH)) {
489 3
                $files[] = $file->getPathname();
490
            } else {
491 2
                $files[] = $file->getFilename();
492
            }
493
        }
494 3
        return $files;
495
    }
496
497
    /**
498
     * @ignore
499
     */
500 2
    public function getFileContent($file)
501
    {
502 2
        if ($this->isFile($file)) {
503 2
            return file_get_contents($this->__file($file));
504
        }
505
        return false;
506
    }
507
508
    /**
509
     * @ignore
510
     */
511 1
    public function putFileContent($file, $string, $mode = 0777)
512
    {
513 1
        $this->createDir($this->getDirname($file), $mode);
514 1
        $isCreated = false !== file_put_contents($this->__file($file), $string);
515 1
        $this->chmod($file, $mode, FileConstants::RECURSIVE_DISABLED);
516 1
        return $isCreated;
517
    }
518
519
    /**
520
     * @ignore
521
     */
522 5
    public function deleteFile($file)
523
    {
524 5
        if ($this->isFile($file)) {
525 5
            $this->close($file);
526 5
            return unlink($this->__file($file));
527
        }
528 1
        return true;
529
    }
530
531
    /**
532
     * @ignore
533
     */
534 1
    public function uploadFile($fileMap, $overwrite = true)
535
    {
536 1
        return false;
537
    }
538
539
    /**
540
     * - 从远程下载文件到本地
541
     * @param callback|null $callback 执行中的回调([当前下载的字节], [总字节])
542
     * @param callback|null $finishCallback 执行完成后的回调([本地文件 \SplFileObject])
543
     *
544
     * @ignore
545
     */
546 1
    public function downloadFile($fileMap, $overwrite = true, $callback = null, $finishCallback = null)
547
    {
548 1
        set_time_limit(0);
549 1
        list($fromFile, $toFile) = $this->fileMap($fileMap);
550 1
        $toSpl = $this->spl($toFile, 'wb');
551
        if ($this->isFile($toFile) && false === $overwrite) {
552
            $this->close($toFile);
553
            I::call($finishCallback, [$toSpl]);
554
            return true;
555
        }
556
        $fromSpl = $this->spl($fromFile, 'rb');
557
        $size = 0;
558
        $total = $this->getFilesize($fromFile);
559
        while (false === $fromSpl->eof()) {
560
            $out = $fromSpl->fread($this->_c['buffer']);
561
            $toSpl->fwrite($out);
562
            $size += Strings::byteLength($out);
563
            I::call($callback, [$size, $total]);
564
        }
565
        $this->close([$fromFile, $toFile]);
566
        I::call($finishCallback, [$toSpl]);
567
    }
568
569
    /**
570
     * download() 配置名:ip
571
     */
572
    const C_DOWNLOAD_IP = 'ip';
573
    /**
574
     * download() 配置名:speed
575
     */
576
    const C_DOWNLOAD_SPEED = 'speed';
577
    /**
578
     * download() 配置名:xSendFile
579
     */
580
    const C_DOWNLOAD_X_SEND_FILE = 'xSendFile';
581
    /**
582
     * download() 配置名:xSendFileRoot
583
     */
584
    const C_DOWNLOAD_X_SEND_FILE_ROOT = 'xSendFileRoot';
585
586
    /**
587
     * 服务端给客户端提供下载请求
588
     *
589
     * @param string|array $fileName self::fileMap()
590
     * @param null|array $config 配置项
591
     *      - ip:限特定 IP 访问,数组或逗号字符串,默认为 *,即对所有 IP 不限制
592
     *      - speed:限速,默认不限速(读取速度为1024 * [buffer]),单位 kb/s
593
     *      - xSendFile:是否使用 X-Sendfile 进行下载,默认 false,即不使用。X-Sendfile 缓解了 PHP 的压力,但同时 PHP 将失去对资源的控制权,因为 PHP 并不知道资源发完了没
594
     *      - xSendFileRoot:文件根路径,默认为 /protected/。此时 Nginx 可作如下配置,更多 @link https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/
595
     *      ```nginx.conf
596
     *      location /protected/ {
597
     *          internal; # 表示这个路径只能在 Nginx 内部访问,不能用浏览器直接访问防止未授权的下载
598
     *          alias   /usr/share/nginx/html/protected/; # 别名
599
     *          # root    /usr/share/nginx/html; # 根目录
600
     *      }
601
     *      ```
602
     * @param callback $callback 下载完成后的回调,参数列表:文件属性数组
603
     *
604
     * @return void
605
     * @throws Exception
606
     */
607
    public function download($fileName, $config = null, $callback = null)
608
    {
609
        Header::xPoweredBy();
610
        set_time_limit(0);
611
        list($originName, $downloadName) = $this->fileMap($fileName);
612
        $originName = $this->__file($originName);
613
        try {
614
            $ip = (string) I::get($config, self::C_DOWNLOAD_IP, '*');
615
            if ('*' !== $ip) {
616
                C::assertTrue(Arrays::in((new Request())->getUserIP(), Strings::toArray($ip)), 'http/1.1 403.6 此 IP 禁止访问');
617
            }
618
            if ($this->isFile($originName)) {
619
                $fileSize = $this->getFilesize($originName);
620
                header('Content-type:application/octet-stream');
621
                header('Accept-Ranges:bytes');
622
                header('Content-Length:' . $fileSize);
623
                header('Content-Disposition: attachment; filename=' . $downloadName);
624
                $speed = (int) I::get($config, self::C_DOWNLOAD_SPEED, 0);
625
                $xSendFile = I::get($config, self::C_DOWNLOAD_X_SEND_FILE, false);
626
                $xSendFileRoot = (string) I::get($config, self::C_DOWNLOAD_X_SEND_FILE_ROOT, '/protected/');
627
                if (true === $xSendFile) {
628
                    $path = rtrim($xSendFileRoot, '/') . '/' . $this->getBasename($originName);
629
                    header('X-Accel-Redirect: ' . $path); // Nginx、Cherokee 实现了该头
630
                    header('X-Sendfile: ' . $path); // Apache、Lighttpd v1.5、Cherokee 实现了该头
631
                    header('X-LIGHTTPD-send-file: ' . $path); // Lighttpd v1.4 实现了该头
632
                    if ($speed) {
633
                        header('X-Accel-Limit-Rate: ' . $speed); // 单位 kb/s
634
                    }
635
                } else {
636
                    flush();
637
                    foreach ($this->dataGenerator($originName, true, ($speed ? $speed : $this->_c['buffer'] * 1024)) as $data) {
638
                        echo $data;
639
                        flush();
640
                        $speed > 0 && sleep(1);
641
                    }
642
                }
643
            }
644
        } catch (Exception $e) {
645
            header($e->getMessage());
646
        } finally {
647
            I::call($callback, [$this->_attributes]);
648
            // 必须要终止掉,防止发送其他数据导致错误
649
            die;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
650
        }
651
    }
652
653
    /**
654
     * @ignore
655
     */
656
    public function chown($file, $user, $flags = FileConstants::RECURSIVE_DISABLED)
657
    {
658
        $file = $this->__file($file);
659
        if ($this->isDir($file) && I::hasFlag($flags, FileConstants::RECURSIVE)) {
660
            $files = $this->getLists($file, FileConstants::COMPLETE_PATH | FileConstants::RECURSIVE);
661
            foreach ($files as $subFile) {
662
                /** @scrutinizer ignore-unhandled */@chown($subFile, $user);
663
            }
664
        } elseif ($this->isFile($file)) {
665
            return /** @scrutinizer ignore-unhandled */@chown($file, $user);
666
        } else {
667
            return false;
668
        }
669
    }
670
671
    /**
672
     * @ignore
673
     */
674
    public function chgrp($file, $group, $flags = FileConstants::RECURSIVE_DISABLED)
675
    {
676
        $file = $this->__file($file);
677
        if ($this->isDir($file) && I::hasFlag($flags, FileConstants::RECURSIVE)) {
678
            $files = $this->getLists($file, FileConstants::COMPLETE_PATH | FileConstants::RECURSIVE);
679
            foreach ($files as $subFile) {
680
                /** @scrutinizer ignore-unhandled */@chgrp($subFile, $group);
681
            }
682
        } elseif ($this->isFile($file)) {
683
            return /** @scrutinizer ignore-unhandled */@chgrp($file, $group);
684
        } else {
685
            return false;
686
        }
687
    }
688
689
    /**
690
     * @ignore
691
     */
692 18
    public function chmod($file, $mode = 0777, $flags = FileConstants::RECURSIVE_DISABLED)
693
    {
694 18
        $file = $this->__file($file);
695 18
        if ($this->isDir($file) && I::hasFlag($flags, FileConstants::RECURSIVE)) {
696 1
            $files = $this->getLists($file, FileConstants::COMPLETE_PATH | FileConstants::RECURSIVE);
697 1
            foreach ($files as $subFile) {
698 1
                /** @scrutinizer ignore-unhandled */@chmod($subFile, $mode);
699
            }
700
        } else {
701 18
            return /** @scrutinizer ignore-unhandled */@chmod($file, $mode);
702
        }
703 1
    }
704
705
    /**
706
     * @ignore
707
     */
708
    public function symlink($from, $to)
709
    {
710
        $from = $this->__file($from);
711
        $to = $this->__file($to);
712
        return @symlink($from, $to);
713
    }
714
715
    /**
716
     * @ignore
717
     */
718 36
    public function close($fileName = null)
719
    {
720 36
        if (is_string($fileName)) {
721 8
            $fileName = [$this->__hash($this->getRealpath($fileName))];
722 36
        } elseif (is_array($fileName)) {
723
            foreach ($fileName as $k => $name) {
724
                $fileName[$k] = $this->__hash($this->getRealpath($name));
725
            }
726
        }
727 36
        foreach ($this->_attributes as $hashName => /** @scrutinizer ignore-unused */$attribute) {
728 17
            if (null === $fileName || is_array($fileName) && in_array($hashName, $fileName)) {
729 17
                unset($this->_attributes[$hashName]);
730
            }
731
        }
732 36
        return true;
733
    }
734
735
    /**
736
     * @ignore
737
     */
738 3
    protected function _copy($fromFile, $toFile)
739
    {
740 3
        $fromFile = $this->__file($fromFile);
741 3
        $toFile = $this->__file($toFile);
742 3
        return copy($fromFile, $toFile);
743
    }
744
745
    /**
746
     * @ignore
747
     */
748 1
    protected function _move($fromFile, $toFile)
749
    {
750 1
        $fromFile = $this->__file($fromFile);
751 1
        $toFile = $this->__file($toFile);
752 1
        return rename($fromFile, $toFile);
753
    }
754
755
    /**
756
     * @ignore
757
     */
758 1
    protected function _mkdir($dir, $mode = 0777)
759
    {
760 1
        $dir = $this->__file($dir);
761 1
        return mkdir($dir, $mode);
762
    }
763
764
    /**
765
     * @ignore
766
     */
767 1
    protected function _rmdir($dir)
768
    {
769 1
        $dir = $this->__file($dir);
770 1
        return rmdir($dir);
771
    }
772
773
}
774