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:
Complex classes like MediaUploadHandler 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 MediaUploadHandler, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
30 | class MediaUploadHandler |
||
31 | { |
||
32 | const PRINT_RESPONSE = true; |
||
33 | const NOT_PRINT_RESPONSE = false; |
||
34 | |||
35 | /** |
||
36 | * @var array Options for upload handler, can be overridden over class constructs. |
||
37 | */ |
||
38 | protected $options = []; |
||
39 | /** |
||
40 | * @var array Used to generate response. |
||
41 | */ |
||
42 | protected $response = []; |
||
43 | /** |
||
44 | * @var array Grouping files based on its extension. |
||
45 | */ |
||
46 | protected $fileTypes = [ |
||
47 | 'image' => [ |
||
48 | 'extensions' => '/\.(gif|jpg|jpeg|png)$/i', |
||
49 | ], |
||
50 | 'audio' => [ |
||
51 | 'extensions' => '/\.(m4a|mp3|wav|wma|oga)$/i', |
||
52 | 'mime_icon' => 'img/mime/audio.png', |
||
53 | ], |
||
54 | 'video' => [ |
||
55 | 'extensions' => '/\.(3gp|mkv|flv|og?(a|g)|avi|mov|wmv|mp4|m4p|mp?(g|2|eg|e|v))$/i', |
||
56 | 'mime_icon' => 'img/mime/video.png', |
||
57 | ], |
||
58 | 'pdf' => [ |
||
59 | 'extensions' => '/\.(pdf|xps)$/i', |
||
60 | 'mime_icon' => 'img/mime/pdf.png', |
||
61 | ], |
||
62 | 'spreadsheet' => [ |
||
63 | 'extensions' => '/\.(xls|xlsx|ods|csv|xml)$/i', |
||
64 | 'mime_icon' => 'img/mime/spreadsheet.png', |
||
65 | ], |
||
66 | 'document' => [ |
||
67 | 'extensions' => '/\.(doc?(m|x)|odt)$/i', |
||
68 | 'mime_icon' => 'img/mime/document.png', |
||
69 | ], |
||
70 | 'archive' => [ |
||
71 | 'extensions' => '/\.(rar|zip|tar|7zip)$/i', |
||
72 | 'mime_icon' => 'img/mime/archive.png', |
||
73 | ], |
||
74 | 'code' => [ |
||
75 | 'extensions' => '/\.(php|c?pp|java|vb?s|html|js|css)$/i', |
||
76 | 'mime_icon' => 'img/mime/audio.png', |
||
77 | ], |
||
78 | 'interactive' => [ |
||
79 | 'extensions' => '/\.(ppt|pptx|odp)$/i', |
||
80 | 'icon' => 'img/mime/interactive.png', |
||
81 | ], |
||
82 | 'text' => [ |
||
83 | 'extensions' => '/\.(txt|md|bat)$/i', |
||
84 | 'mime_icon' => 'img/mime/text.png', |
||
85 | ], |
||
86 | ]; |
||
87 | |||
88 | /** |
||
89 | * @var Media |
||
90 | */ |
||
91 | private $_media; |
||
92 | /** |
||
93 | * @var array Used to create Media Meta. |
||
94 | */ |
||
95 | private $_meta; |
||
96 | |||
97 | /** |
||
98 | * Create object of MediaUploadHandler. |
||
99 | * |
||
100 | * @param array|null $options |
||
101 | * @param bool $initialize |
||
102 | */ |
||
103 | public function __construct($options = null, $initialize = true) |
||
114 | |||
115 | /** |
||
116 | * Initialize the action of MediaUploadHandler based on request method if set true. |
||
117 | */ |
||
118 | protected function initialize() |
||
140 | |||
141 | /** |
||
142 | * Get server var based on id. Return null when it's not exist. |
||
143 | * |
||
144 | * @param $id |
||
145 | * @return mixed |
||
146 | */ |
||
147 | protected function getServerVar($id) |
||
155 | |||
156 | /** |
||
157 | * Get singular param name. |
||
158 | * |
||
159 | * @return string |
||
160 | */ |
||
161 | protected function getSingularParamName() |
||
165 | |||
166 | /** |
||
167 | * Adds a new header. |
||
168 | * If there is already a header with the same name, it will be replaced. |
||
169 | * |
||
170 | * @param string $name The name of the header. |
||
171 | * @param string $value The value of the header. |
||
172 | */ |
||
173 | protected function setHeader($name, $value = '') |
||
177 | |||
178 | /** |
||
179 | * Set header content-type. |
||
180 | */ |
||
181 | protected function sendContentTypeHeader() |
||
191 | |||
192 | /** |
||
193 | * Set header Access-Control-*. |
||
194 | */ |
||
195 | protected function sendAccessControlHeaders() |
||
205 | |||
206 | /** |
||
207 | * Finds the Media model based on its primary key value. |
||
208 | * If the model is not found it will return null. |
||
209 | * |
||
210 | * @param integer $id |
||
211 | * @return Media|array |
||
212 | */ |
||
213 | protected function findMedia($id) |
||
221 | |||
222 | /** |
||
223 | * Finds the Post model based on its primary key value. |
||
224 | * If the model is not found it will return null. |
||
225 | * |
||
226 | * @param integer $id |
||
227 | * @return Post|null |
||
228 | */ |
||
229 | protected function findPost($id) |
||
237 | |||
238 | /** |
||
239 | * Get user path of login user. It can be disabled by override config, set user_dirs to false. |
||
240 | * |
||
241 | * @return string The username of login user. |
||
242 | */ |
||
243 | protected function getUserPath() |
||
251 | |||
252 | /** |
||
253 | * Year-month path generated by date function can be disable by set year_month_path to false. |
||
254 | * |
||
255 | * @return string date(/Y/m). |
||
256 | */ |
||
257 | protected function getYearMonthPath() |
||
265 | |||
266 | /** |
||
267 | * Get upload path based on current config, generate upload_dir/user_path/y/m/filename.ext. |
||
268 | * |
||
269 | * @param null $fileName Filename and extension (filename.ext). |
||
270 | * @return string |
||
271 | */ |
||
272 | protected function getUploadPath($fileName = null) |
||
276 | |||
277 | /** |
||
278 | * Get file-path of the filename. |
||
279 | * |
||
280 | * @param string|null $fileName |
||
281 | * @return string |
||
282 | */ |
||
283 | protected function getFilePath($fileName = null) |
||
287 | |||
288 | /** |
||
289 | * Generate slug for uploaded file. |
||
290 | * Replace all space to - and transform all character to lowercase. |
||
291 | * |
||
292 | * @param string $fileName |
||
293 | * @param array $replace The replace_pairs parameter may be used as a substitute for to and from in which case. |
||
294 | * it's an array in the form array('from' => 'to', ...). |
||
295 | * @param string $delimiter |
||
296 | * @see strtr |
||
297 | * @return string Clean name |
||
298 | */ |
||
299 | protected function generateSlug($fileName, $replace = [], $delimiter = '-') |
||
315 | |||
316 | /** |
||
317 | * Callback function of upCountName. |
||
318 | * |
||
319 | * @param array $matches |
||
320 | * @return string |
||
321 | */ |
||
322 | protected function upCountNameCallback($matches) |
||
329 | |||
330 | /** |
||
331 | * The number before fileName extension is replaced by upCountNameCallback. |
||
332 | * |
||
333 | * @param string $fileName |
||
334 | * @return mixed |
||
335 | * @see upCountNameCallback |
||
336 | */ |
||
337 | protected function upCountName($fileName) |
||
341 | |||
342 | /** |
||
343 | * Get filename of uploaded file. |
||
344 | * If the filename is already exist in the upload directory |
||
345 | * then the number between - and before the extension plus 1. |
||
346 | * |
||
347 | * @param UploadedFile $file |
||
348 | * @return string |
||
349 | */ |
||
350 | protected function getFileName($file) |
||
373 | |||
374 | /** |
||
375 | * @param \imagine\image\ImageInterface $image |
||
376 | * @param string $filePath |
||
377 | * @return bool |
||
378 | */ |
||
379 | protected function correctExifRotation($image, $filePath) |
||
411 | |||
412 | /** |
||
413 | * @param $fileName |
||
414 | * @param $version |
||
415 | * @param $options |
||
416 | * @return bool|\imagine\Image\ManipulatorInterface |
||
417 | */ |
||
418 | protected function createScaledImage($fileName, $version, $options) |
||
489 | |||
490 | /** |
||
491 | * Handle image file. |
||
492 | * |
||
493 | * @param string $fileName |
||
494 | */ |
||
495 | protected function handleImageFile($fileName) |
||
503 | |||
504 | /** |
||
505 | * Set icon url. |
||
506 | * |
||
507 | * @param string $fileName |
||
508 | * @return string |
||
509 | */ |
||
510 | protected function setIconUrl($fileName) |
||
524 | |||
525 | /** |
||
526 | * Handle uploaded file. If the uploaded file is valid image type, the file will be resize or crop |
||
527 | * based on versions in options. |
||
528 | * |
||
529 | * @param UploadedFile $file |
||
530 | */ |
||
531 | protected function handleFileUpload($file) |
||
557 | |||
558 | /** |
||
559 | * @return \yii\data\Pagination |
||
560 | */ |
||
561 | protected function getPages() |
||
571 | |||
572 | /** |
||
573 | * @param $pages Pagination |
||
574 | * @return array |
||
575 | */ |
||
576 | protected function getPaging($pages) |
||
601 | |||
602 | /** |
||
603 | * Set options of upload Handler. |
||
604 | * |
||
605 | * @param array $options |
||
606 | */ |
||
607 | public function setOptions($options = []) |
||
658 | |||
659 | /** |
||
660 | * Get all of MediaUploadHandler Options. |
||
661 | */ |
||
662 | public function getOptions() |
||
666 | |||
667 | /** |
||
668 | * Get single option of MediaUploadHandler. |
||
669 | * Return string or array if option exist, or return null if not exist. |
||
670 | * |
||
671 | * @param string $id |
||
672 | * @return string|array|null |
||
673 | */ |
||
674 | public function getOption($id) |
||
682 | |||
683 | /** |
||
684 | * Generate response based on Media primary key. |
||
685 | * |
||
686 | * @param Media $media |
||
687 | * @return array |
||
688 | */ |
||
689 | public function generateResponse($media) |
||
715 | |||
716 | /** |
||
717 | * Set response. |
||
718 | * |
||
719 | * @param array $response |
||
720 | */ |
||
721 | public function setResponse($response) |
||
725 | |||
726 | |||
727 | /** |
||
728 | * Generate response in the form of a string of json. |
||
729 | * |
||
730 | * @param bool $printResponse |
||
731 | * @return array |
||
732 | */ |
||
733 | public function getResponse($printResponse = self::PRINT_RESPONSE) |
||
749 | |||
750 | /** |
||
751 | * Set response header. |
||
752 | */ |
||
753 | public function head() |
||
765 | |||
766 | /** |
||
767 | * Get media files. |
||
768 | * |
||
769 | * @param int $id |
||
770 | * @param bool $printResponse |
||
771 | * @return array |
||
772 | */ |
||
773 | public function get($id = null, $printResponse = self::PRINT_RESPONSE) |
||
806 | |||
807 | /** |
||
808 | * Upload file to server. |
||
809 | * |
||
810 | * @param bool $printResponse |
||
811 | * @return array |
||
812 | */ |
||
813 | public function post($printResponse = self::PRINT_RESPONSE) |
||
852 | |||
853 | /** |
||
854 | * Delete files based on media primary key |
||
855 | * |
||
856 | * @param int $id Primary key of Media |
||
857 | * @param bool $printResponse |
||
858 | * @return array |
||
859 | * @throws \Exception |
||
860 | */ |
||
861 | public function delete($id, $printResponse = self::PRINT_RESPONSE) |
||
880 | } |
||
881 |
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.