File::getName()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 7
ccs 0
cts 5
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: liu21st <[email protected]>
10
// +----------------------------------------------------------------------
11
declare (strict_types = 1);
12
13
namespace think;
14
15
use SplFileInfo;
16
use think\exception\FileException;
17
18
/**
19
 * 文件上传类
20
 * @package think
21
 */
22
class File extends SplFileInfo
23
{
24
25
    /**
26
     * 文件hash规则
27
     * @var array
28
     */
29
    protected $hash = [];
30
31
    protected $hashName;
32
33
    public function __construct(string $path, bool $checkPath = true)
34
    {
35
        if ($checkPath && !is_file($path)) {
36
            throw new FileException(sprintf('The file "%s" does not exist', $path));
37
        }
38
39
        parent::__construct($path);
40
    }
41
42
    /**
43
     * 获取文件的哈希散列值
44
     * @access public
45
     * @param string $type
46
     * @return string
47
     */
48
    public function hash(string $type = 'sha1'): string
49
    {
50
        if (!isset($this->hash[$type])) {
51
            $this->hash[$type] = hash_file($type, $this->getPathname());
52
        }
53
54
        return $this->hash[$type];
55
    }
56
57
    /**
58
     * 获取文件的MD5值
59
     * @access public
60
     * @return string
61
     */
62
    public function md5(): string
63
    {
64
        return $this->hash('md5');
65
    }
66
67
    /**
68
     * 获取文件的SHA1值
69
     * @access public
70
     * @return string
71
     */
72
    public function sha1(): string
73
    {
74
        return $this->hash('sha1');
75
    }
76
77
    /**
78
     * 获取文件类型信息
79
     * @access public
80
     * @return string
81
     */
82
    public function getMime(): string
83
    {
84
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
85
86
        return finfo_file($finfo, $this->getPathname());
87
    }
88
89
    /**
90
     * 移动文件
91
     * @access public
92
     * @param string      $directory 保存路径
93
     * @param string|null $name      保存的文件名
94
     * @return File
95
     */
96
    public function move(string $directory, string $name = null): File
97
    {
98
        $target = $this->getTargetFile($directory, $name);
99
100
        set_error_handler(function ($type, $msg) use (&$error) {
101
            $error = $msg;
102
        });
103
        $renamed = rename($this->getPathname(), (string) $target);
104
        restore_error_handler();
105
        if (!$renamed) {
106
            throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error)));
107
        }
108
109
        @chmod((string) $target, 0666 & ~umask());
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

109
        /** @scrutinizer ignore-unhandled */ @chmod((string) $target, 0666 & ~umask());

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
110
111
        return $target;
112
    }
113
114
    /**
115
     * 实例化一个新文件
116
     * @param string      $directory
117
     * @param null|string $name
118
     * @return File
119
     */
120
    protected function getTargetFile(string $directory, string $name = null): File
121
    {
122
        if (!is_dir($directory)) {
123
            if (false === @mkdir($directory, 0777, true) && !is_dir($directory)) {
124
                throw new FileException(sprintf('Unable to create the "%s" directory', $directory));
125
            }
126
        } elseif (!is_writable($directory)) {
127
            throw new FileException(sprintf('Unable to write in the "%s" directory', $directory));
128
        }
129
130
        $target = rtrim($directory, '/\\') . \DIRECTORY_SEPARATOR . (null === $name ? $this->getBasename() : $this->getName($name));
131
132
        return new self($target, false);
133
    }
134
135
    /**
136
     * 获取文件名
137
     * @param string $name
138
     * @return string
139
     */
140
    protected function getName(string $name): string
141
    {
142
        $originalName = str_replace('\\', '/', $name);
143
        $pos          = strrpos($originalName, '/');
144
        $originalName = false === $pos ? $originalName : substr($originalName, $pos + 1);
145
146
        return $originalName;
147
    }
148
149
    /**
150
     * 文件扩展名
151
     * @return string
152
     */
153
    public function extension(): string
154
    {
155
        return $this->getExtension();
156
    }
157
158
    /**
159
     * 自动生成文件名
160
     * @access public
161
     * @param string|\Closure $rule
162
     * @return string
163
     */
164
    public function hashName($rule = ''): string
165
    {
166
        if (!$this->hashName) {
167
            if ($rule instanceof \Closure) {
168
                $this->hashName = call_user_func_array($rule, [$this]);
169
            } else {
170
                switch (true) {
171
                    case in_array($rule, hash_algos()):
172
                        $hash           = $this->hash($rule);
173
                        $this->hashName = substr($hash, 0, 2) . DIRECTORY_SEPARATOR . substr($hash, 2);
174
                        break;
175
                    case is_callable($rule):
176
                        $this->hashName = call_user_func($rule);
177
                        break;
178
                    default:
179
                        $this->hashName = date('Ymd') . DIRECTORY_SEPARATOR . md5(microtime(true) . $this->getPathname());
180
                        break;
181
                }
182
            }
183
        }
184
185
        return $this->hashName . '.' . $this->extension();
186
    }
187
}
188