Complex classes like UploadedFile often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use UploadedFile, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
42 | class UploadedFile extends BaseObject implements UploadedFileInterface |
||
43 | { |
||
44 | /** |
||
45 | * @var string the path of the uploaded file on the server. |
||
46 | * Note, this is a temporary file which will be automatically deleted by PHP |
||
47 | * after the current request is processed. |
||
48 | */ |
||
49 | public $tempFilename; |
||
50 | |||
51 | /** |
||
52 | * @var string the original name of the file being uploaded |
||
53 | */ |
||
54 | private $_clientFilename; |
||
55 | /** |
||
56 | * @var string the MIME-type of the uploaded file (such as "image/gif"). |
||
57 | * Since this MIME type is not checked on the server-side, do not take this value for granted. |
||
58 | * Instead, use [[\yii\helpers\FileHelper::getMimeType()]] to determine the exact MIME type. |
||
59 | */ |
||
60 | private $_clientMediaType; |
||
61 | /** |
||
62 | * @var int the actual size of the uploaded file in bytes |
||
63 | */ |
||
64 | private $_size; |
||
65 | /** |
||
66 | * @var int an error code describing the status of this file uploading. |
||
67 | * @see http://www.php.net/manual/en/features.file-upload.errors.php |
||
68 | */ |
||
69 | private $_error; |
||
70 | /** |
||
71 | * @var StreamInterface stream for this file. |
||
72 | * @since 2.1.0 |
||
73 | */ |
||
74 | private $_stream; |
||
75 | |||
76 | private static $_files; |
||
77 | |||
78 | |||
79 | /** |
||
80 | * String output. |
||
81 | * This is PHP magic method that returns string representation of an object. |
||
82 | * The implementation here returns the uploaded file's name. |
||
83 | * @return string the string representation of the object |
||
84 | */ |
||
85 | public function __toString() |
||
89 | |||
90 | /** |
||
91 | * Returns an uploaded file for the given model attribute. |
||
92 | * The file should be uploaded using [[\yii\widgets\ActiveField::fileInput()]]. |
||
93 | * @param \yii\base\Model $model the data model |
||
94 | * @param string $attribute the attribute name. The attribute name may contain array indexes. |
||
95 | * For example, '[1]file' for tabular file uploading; and 'file[1]' for an element in a file array. |
||
96 | * @return UploadedFile the instance of the uploaded file. |
||
97 | * Null is returned if no file is uploaded for the specified model attribute. |
||
98 | * @see getInstanceByName() |
||
99 | */ |
||
100 | public static function getInstance($model, $attribute) |
||
105 | |||
106 | /** |
||
107 | * Returns all uploaded files for the given model attribute. |
||
108 | * @param \yii\base\Model $model the data model |
||
109 | * @param string $attribute the attribute name. The attribute name may contain array indexes |
||
110 | * for tabular file uploading, e.g. '[1]file'. |
||
111 | * @return UploadedFile[] array of UploadedFile objects. |
||
112 | * Empty array is returned if no available file was found for the given attribute. |
||
113 | */ |
||
114 | public static function getInstances($model, $attribute) |
||
119 | |||
120 | /** |
||
121 | * Returns an uploaded file according to the given file input name. |
||
122 | * The name can be a plain string or a string like an array element (e.g. 'Post[imageFile]', or 'Post[0][imageFile]'). |
||
123 | * @param string $name the name of the file input field. |
||
124 | * @return null|UploadedFile the instance of the uploaded file. |
||
125 | * Null is returned if no file is uploaded for the specified name. |
||
126 | */ |
||
127 | public static function getInstanceByName($name) |
||
132 | |||
133 | /** |
||
134 | * Returns an array of uploaded files corresponding to the specified file input name. |
||
135 | * This is mainly used when multiple files were uploaded and saved as 'files[0]', 'files[1]', |
||
136 | * 'files[n]'..., and you can retrieve them all by passing 'files' as the name. |
||
137 | * @param string $name the name of the array of files |
||
138 | * @return UploadedFile[] the array of UploadedFile objects. Empty array is returned |
||
139 | * if no adequate upload was found. Please note that this array will contain |
||
140 | * all files from all sub-arrays regardless how deeply nested they are. |
||
141 | */ |
||
142 | public static function getInstancesByName($name) |
||
156 | |||
157 | /** |
||
158 | * Cleans up the loaded UploadedFile instances. |
||
159 | * This method is mainly used by test scripts to set up a fixture. |
||
160 | */ |
||
161 | public static function reset() |
||
165 | |||
166 | /** |
||
167 | * Saves the uploaded file. |
||
168 | * Note that this method uses php's move_uploaded_file() method. If the target file `$file` |
||
169 | * already exists, it will be overwritten. |
||
170 | * @param string $file the file path used to save the uploaded file |
||
171 | * @param bool $deleteTempFile whether to delete the temporary file after saving. |
||
172 | * If true, you will not be able to save the uploaded file again in the current request. |
||
173 | * @return bool true whether the file is saved successfully |
||
174 | * @see error |
||
175 | */ |
||
176 | public function saveAs($file, $deleteTempFile = true) |
||
188 | |||
189 | /** |
||
190 | * @return string original file base name |
||
191 | */ |
||
192 | public function getBaseName() |
||
198 | |||
199 | /** |
||
200 | * @return string file extension |
||
201 | */ |
||
202 | public function getExtension() |
||
206 | |||
207 | /** |
||
208 | * @return bool whether there is an error with the uploaded file. |
||
209 | * Check [[error]] for detailed error code information. |
||
210 | */ |
||
211 | public function getHasError() |
||
215 | |||
216 | /** |
||
217 | * Creates UploadedFile instances from $_FILE. |
||
218 | * @return array the UploadedFile instances |
||
219 | */ |
||
220 | private static function loadFiles() |
||
232 | |||
233 | /** |
||
234 | * Creates UploadedFile instances from $_FILE recursively. |
||
235 | * @param string $key key for identifying uploaded file: class name and sub-array indexes |
||
236 | * @param mixed $names file names provided by PHP |
||
237 | * @param mixed $tempNames temporary file names provided by PHP |
||
238 | * @param mixed $types file types provided by PHP |
||
239 | * @param mixed $sizes file sizes provided by PHP |
||
240 | * @param mixed $errors uploading issues provided by PHP |
||
241 | */ |
||
242 | private static function loadFilesRecursive($key, $names, $tempNames, $types, $sizes, $errors) |
||
258 | |||
259 | /** |
||
260 | * {@inheritdoc} |
||
261 | * @since 2.1.0 |
||
262 | */ |
||
263 | public function getStream() |
||
285 | |||
286 | /** |
||
287 | * @param StreamInterface|\Closure|array $stream stream instance or its DI compatible configuration. |
||
288 | * @since 2.1.0 |
||
289 | */ |
||
290 | public function setStream($stream) |
||
294 | |||
295 | /** |
||
296 | * {@inheritdoc} |
||
297 | * @since 2.1.0 |
||
298 | */ |
||
299 | public function moveTo($targetPath) |
||
308 | |||
309 | /** |
||
310 | * {@inheritdoc} |
||
311 | * @since 2.1.0 |
||
312 | */ |
||
313 | public function getSize() |
||
317 | |||
318 | /** |
||
319 | * @param int $size the actual size of the uploaded file in bytes. |
||
320 | * @throws InvalidArgumentException on invalid size given. |
||
321 | * @since 2.1.0 |
||
322 | */ |
||
323 | public function setSize($size) |
||
330 | |||
331 | /** |
||
332 | * {@inheritdoc} |
||
333 | * @since 2.1.0 |
||
334 | */ |
||
335 | public function getError() |
||
339 | |||
340 | /** |
||
341 | * @param int $error upload error code. |
||
342 | * @throws InvalidArgumentException on invalid error given. |
||
343 | * @since 2.1.0 |
||
344 | */ |
||
345 | public function setError($error) |
||
352 | |||
353 | /** |
||
354 | * {@inheritdoc} |
||
355 | * @since 2.1.0 |
||
356 | */ |
||
357 | public function getClientFilename() |
||
361 | |||
362 | /** |
||
363 | * @param string $clientFilename the original name of the file being uploaded. |
||
364 | * @since 2.1.0 |
||
365 | */ |
||
366 | public function setClientFilename($clientFilename) |
||
370 | |||
371 | /** |
||
372 | * {@inheritdoc} |
||
373 | * @since 2.1.0 |
||
374 | */ |
||
375 | public function getClientMediaType() |
||
379 | |||
380 | /** |
||
381 | * @param string $clientMediaType the MIME-type of the uploaded file (such as "image/gif"). |
||
382 | * @since 2.1.0 |
||
383 | */ |
||
384 | public function setClientMediaType($clientMediaType) |
||
388 | } |
||
389 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.