FileUpload   A
last analyzed

Complexity

Total Complexity 26

Size/Duplication

Total Lines 205
Duplicated Lines 1.95 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 26
lcom 1
cbo 2
dl 4
loc 205
rs 10
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 3
A read() 0 10 2
A nameUnsafe() 0 4 1
A sizeUnsafe() 0 4 1
A mimeTypeUnsafe() 0 4 1
A error() 0 4 1
A errorMessage() 0 18 3
A extensionUnsafe() 0 4 1
A isValid() 0 4 2
B getMaxFileSize() 0 34 8
A move() 4 17 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * @license MIT
4
 */
5
namespace Pivasic\Bundle\Common\File;
6
7
use Pivasic\Bundle\Common\File\Exception\FileException;
8
9
/**
10
 * Class FileUpload
11
 * @package Pivasic\Bundle\Common\File
12
 */
13
class FileUpload extends File
14
{
15
    /**
16
     * @param string $path
17
     * @param string $name
18
     * @param int $size
19
     * @param string $mimeType
20
     * @param null $error
21
     */
22
    public function __construct(string $path, string $name, int $size = 0, string $mimeType = '', $error = null)
23
    {
24
        $this->name = $this->getName($name);
25
        $this->size = $size;
26
        $this->mimeType = $mimeType ?: 'application/octet-stream';
27
        $this->error = $error ?: UPLOAD_ERR_OK;
28
29
        parent::__construct($path, UPLOAD_ERR_OK == $this->error);
30
    }
31
32
    /**
33
     * Get file content.
34
     *
35
     * @return string|mixed
36
     */
37
    public function read()
38
    {
39
        $data = '';
40
        $fileObj = $this->openFile();
41
        while (!$fileObj->eof()) {
42
            $data .= $fileObj->fread(4096);
43
        }
44
        $fileObj = null;
0 ignored issues
show
Unused Code introduced by
$fileObj is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
45
        return $data;
46
    }
47
48
    /**
49
     * Returns the original file name.
50
     *
51
     * It is extracted from the request from which the file has been uploaded.
52
     * Then it should not be considered as a safe value.
53
     *
54
     * @return string The original name
55
     */
56
    public function nameUnsafe(): string
57
    {
58
        return $this->name;
59
    }
60
61
    /**
62
     * Returns the file size.
63
     *
64
     * It is extracted from the request from which the file has been uploaded.
65
     * Then it should not be considered as a safe value.
66
     *
67
     * @return int The file size
68
     */
69
    public function sizeUnsafe(): int
70
    {
71
        return $this->size;
72
    }
73
74
    /**
75
     * Returns the file mime type.
76
     *
77
     * The client mime type is extracted from the request from which the file
78
     * was uploaded, so it should not be considered as a safe value.
79
     *
80
     * @return string The mime type
81
     */
82
    public function mimeTypeUnsafe(): string
83
    {
84
        return $this->mimeType;
85
    }
86
87
    /**
88
     * Returns the upload error.
89
     *
90
     * If the upload was successful, the constant UPLOAD_ERR_OK is returned.
91
     * Otherwise one of the other UPLOAD_ERR_XXX constants is returned.
92
     *
93
     * @return int The upload error
94
     */
95
    public function error()
96
    {
97
        return $this->error;
98
    }
99
100
    /**
101
     * Returns an informative upload error message.
102
     *
103
     * @return string The error message regarding the specified error code
104
     */
105
    public function errorMessage(): string
106
    {
107
        static $errors = array(
108
            UPLOAD_ERR_INI_SIZE => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d KiB).',
109
            UPLOAD_ERR_FORM_SIZE => 'The file "%s" exceeds the upload limit defined in your form.',
110
            UPLOAD_ERR_PARTIAL => 'The file "%s" was only partially uploaded.',
111
            UPLOAD_ERR_NO_FILE => 'No file was uploaded.',
112
            UPLOAD_ERR_CANT_WRITE => 'The file "%s" could not be written on disk.',
113
            UPLOAD_ERR_NO_TMP_DIR => 'File could not be uploaded: missing temporary directory.',
114
            UPLOAD_ERR_EXTENSION => 'File upload was stopped by a PHP extension.',
115
        );
116
117
        $errorCode = $this->error;
118
        $maxFileSize = $errorCode === UPLOAD_ERR_INI_SIZE ? $this->getMaxFileSize() / 1024 : 0;
119
        $message = isset($errors[$errorCode]) ? $errors[$errorCode] : 'The file "%s" was not uploaded due to an unknown error.';
120
121
        return sprintf($message, $this->name, $maxFileSize);
122
    }
123
124
    /**
125
     * Returns the original file extension.
126
     *
127
     * It is extracted from the original file name that was uploaded.
128
     * Then it should not be considered as a safe value.
129
     *
130
     * @return string The extension
131
     */
132
    public function extensionUnsafe(): string
133
    {
134
        return pathinfo($this->name, PATHINFO_EXTENSION);
135
    }
136
137
    /**
138
     * Returns whether the file was uploaded successfully.
139
     *
140
     * @return bool True if the file has been uploaded with HTTP and no error occurred.
141
     */
142
    public function isValid(): bool
143
    {
144
        return $this->error === UPLOAD_ERR_OK && is_uploaded_file($this->getPathname());
145
    }
146
147
    /**
148
     * Returns the maximum size of an uploaded file as configured in php.ini.
149
     *
150
     * @return int The maximum size of an uploaded file in bytes
151
     */
152
    public function getMaxFileSize(): int
153
    {
154
        $iniMax = strtolower(ini_get('upload_max_filesize'));
155
156
        if ('' === $iniMax) {
157
            return PHP_INT_MAX;
158
        }
159
160
        $max = ltrim($iniMax, '+');
161
        if (0 === strpos($max, '0x')) {
162
            $max = intval($max, 16);
163
        } elseif (0 === strpos($max, '0')) {
164
            $max = intval($max, 8);
165
        } else {
166
            $max = (int) $max;
167
        }
168
169
        switch (substr($iniMax, -1)) {
170
            case 't':
171
                $max *= 1024;
172
            // no break
173
            case 'g':
174
                $max *= 1024;
175
            // no break
176
            case 'm':
177
                $max *= 1024;
178
            // no break
179
            case 'k':
180
                $max *= 1024;
181
            // no break
182
        }
183
184
        return $max;
185
    }
186
187
    /**
188
     * Moves the file to a new location.
189
     *
190
     * @param string $directory Destination folder
191
     * @param string $name      New file name
192
     * @return File A File object representing the new file
193
     * @throws FileException
194
     */
195
    public function move(string $directory, string $name = ''): File
196
    {
197
        if ($this->isValid()) {
198
            $target = $this->getTargetFile($directory, $name);
199
200 View Code Duplication
            if (!@move_uploaded_file($this->getPathname(), $target)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
201
                $error = error_get_last();
202
                throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message'])));
203
            }
204
205
            $this->customChmod($target);
206
207
            return $target;
208
        }
209
210
        throw new FileException($this->errorMessage());
211
    }
212
213
    private $name;
214
    private $size;
215
    private $mimeType;
216
    private $error;
217
}