Issues (8)

src/File/File.php (3 issues)

1
<?php
2
3
/**
4
 * Platine Upload
5
 *
6
 * Platine Upload provides a flexible file uploads with extensible
7
 * validation and storage strategies.
8
 *
9
 * This content is released under the MIT License (MIT)
10
 *
11
 * Copyright (c) 2020 Platine Upload
12
 *
13
 * @author      Josh Lockhart <[email protected]>
14
 * @copyright   2012 Josh Lockhart
15
 * @link        http://www.joshlockhart.com
16
 * @version     2.0.0
17
 *
18
 * Permission is hereby granted, free of charge, to any person obtaining a copy
19
 * of this software and associated documentation files (the "Software"), to deal
20
 * in the Software without restriction, including without limitation the rights
21
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22
 * copies of the Software, and to permit persons to whom the Software is
23
 * furnished to do so, subject to the following conditions:
24
 *
25
 * The above copyright notice and this permission notice shall be included in all
26
 * copies or substantial portions of the Software.
27
 *
28
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
33
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34
 * SOFTWARE.
35
 */
36
37
/**
38
 *  @file File.php
39
 *
40
 *  The Upload File class
41
 *
42
 *  @package    Platine\Upload\File
43
 *  @author Platine Developers Team
44
 *  @copyright  Copyright (c) 2020
45
 *  @license    http://opensource.org/licenses/MIT  MIT License
46
 *  @link   https://www.platine-php.com
47
 *  @version 1.0.0
48
 *  @filesource
49
 */
50
51
declare(strict_types=1);
52
53
namespace Platine\Upload\File;
54
55
use finfo;
56
use RuntimeException;
57
use SplFileInfo;
58
59
/**
60
 * @class File
61
 * @package Platine\Upload\File
62
 */
63
class File extends SplFileInfo implements FileInterface
64
{
65
    /**
66
     * Factory used to create new instance
67
     * @var callable|null
68
     */
69
    protected static $factory = null;
70
71
    /**
72
     * The file name
73
     * @var string
74
     */
75
    protected string $name;
76
77
    /**
78
     * The file extension
79
     * @var string
80
     */
81
    protected string $extension;
82
83
    /**
84
     * The file mime type
85
     * @var string
86
     */
87
    protected string $mimeType = '';
88
89
    /**
90
     * The upload status
91
     * @var int
92
     */
93
    protected int $error = UPLOAD_ERR_OK;
94
95
96
    /**
97
     * Create new instance
98
     * @param string $filePath the file absolute path
99
     * @param string|null $name the desired new name
100
     * @param int $error
101
     */
102
    public function __construct(
103
        string $filePath,
104
        ?string $name = null,
105
        int $error = UPLOAD_ERR_OK
106
    ) {
107
        $this->error = $error;
108
        $newName = $name === null ? $filePath : $name;
109
110
        $this->setName(pathinfo($newName, PATHINFO_FILENAME));
0 ignored issues
show
It seems like pathinfo($newName, Plati...File\PATHINFO_FILENAME) can also be of type array; however, parameter $name of Platine\Upload\File\File::setName() 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

110
        $this->setName(/** @scrutinizer ignore-type */ pathinfo($newName, PATHINFO_FILENAME));
Loading history...
111
        $this->setExtension(pathinfo($newName, PATHINFO_EXTENSION));
0 ignored issues
show
It seems like pathinfo($newName, Plati...ile\PATHINFO_EXTENSION) can also be of type array; however, parameter $name of Platine\Upload\File\File::setExtension() 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

111
        $this->setExtension(/** @scrutinizer ignore-type */ pathinfo($newName, PATHINFO_EXTENSION));
Loading history...
112
113
        parent::__construct($filePath);
114
    }
115
116
    /**
117
    * {@inheritdoc}
118
    */
119
    public function getExtension(): string
120
    {
121
        return $this->extension;
122
    }
123
124
    /**
125
    * {@inheritdoc}
126
    */
127
    public function setExtension(string $name): self
128
    {
129
        $this->extension = strtolower($name);
130
131
        return $this;
132
    }
133
134
    /**
135
    * {@inheritdoc}
136
    */
137
    public function getFullName(): string
138
    {
139
        return $this->extension === '' ?
140
                $this->name
141
                : sprintf('%s.%s', $this->name, $this->extension);
142
    }
143
144
    /**
145
    * {@inheritdoc}
146
    */
147
    public function getMD5(): string
148
    {
149
        $hash = md5_file($this->getPathname());
150
        return $hash === false ? '' : $hash;
151
    }
152
153
    /**
154
    * {@inheritdoc}
155
    */
156
    public function getPathname(): string
157
    {
158
        return parent::getPathname();
159
    }
160
161
    /**
162
    * {@inheritdoc}
163
    */
164
    public function getSize(): int
165
    {
166
        return parent::getSize();
167
    }
168
169
    /**
170
    * {@inheritdoc}
171
    */
172
    public function getMimeType(): string
173
    {
174
        if (empty($this->mimeType)) {
175
            $finfo = new finfo(FILEINFO_MIME);
176
            $mimeType = $finfo->file($this->getPathname());
177
            if ($mimeType !== false) {
178
                $mimetypeParts = preg_split('/\s*[;,]\s*/', $mimeType);
179
                if (is_array($mimetypeParts)) {
0 ignored issues
show
The condition is_array($mimetypeParts) is always true.
Loading history...
180
                    $this->mimeType = strtolower($mimetypeParts[0]);
181
                }
182
            }
183
            unset($finfo);
184
        }
185
186
        return $this->mimeType;
187
    }
188
189
    /**
190
    * {@inheritdoc}
191
    */
192
    public function getName(): string
193
    {
194
        return $this->name;
195
    }
196
197
    /**
198
    * {@inheritdoc}
199
    */
200
    public function setName(string $name): self
201
    {
202
        $cleanName = preg_replace('/[^A-Za-z0-9\.]+/', '_', $name);
203
        if ($cleanName !== null) {
204
            $filename = basename($cleanName);
205
            $this->name = $filename;
206
        }
207
208
        return $this;
209
    }
210
211
    /**
212
    * {@inheritdoc}
213
    */
214
    public function getError(): int
215
    {
216
        return $this->error;
217
    }
218
219
    /**
220
     * Set the factory used to create new instance
221
     * @param callable|null $callable
222
     * @return void
223
     */
224
    public static function setFactory(?callable $callable = null): void
225
    {
226
        static::$factory = $callable;
227
    }
228
229
    /**
230
     * Create new instance of this class
231
     * @param string $tmpName
232
     * @param string|null $name
233
     * @param int $error
234
     * @return self
235
     */
236
    public static function create(
237
        string $tmpName,
238
        ?string $name = null,
239
        int $error = UPLOAD_ERR_OK
240
    ): self {
241
        if (static::$factory !== null) {
242
            $file = call_user_func_array(static::$factory, [$tmpName, $name, $error]);
243
244
            if (!$file instanceof File) {
245
                throw new RuntimeException(sprintf(
246
                    'The File factory must return an instance of [%s]',
247
                    File::class
248
                ));
249
            }
250
251
            return $file;
252
        }
253
254
        return new self($tmpName, $name, $error);
255
    }
256
}
257