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 SharefileAdapter 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 SharefileAdapter, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
21 | class SharefileAdapter extends AbstractAdapter |
||
22 | { |
||
23 | use StreamedTrait; |
||
24 | use NotSupportingVisibilityTrait; |
||
25 | |||
26 | /** ShareFile access control constants */ |
||
27 | const CAN_ADD_FOLDER = 'CanAddFolder'; |
||
28 | const ADD_NODE = 'CanAddNode'; |
||
29 | const CAN_VIEW = 'CanView'; |
||
30 | const CAN_DOWNLOAD = 'CanDownload'; |
||
31 | const CAN_UPLOAD = 'CanUpload'; |
||
32 | const CAN_SEND = 'CanSend'; |
||
33 | const CAN_DELETE_CURRENT_ITEM = 'CanDeleteCurrentItem'; |
||
34 | const CAN_DELETE_CHILD_ITEMS = 'CanDeleteChildItems'; |
||
35 | const CAN_MANAGE_PERMISSIONS = 'CanManagePermissions'; |
||
36 | const CAN_CREATEOFFICE_DOCUMENTS = 'CanCreateOfficeDocuments'; |
||
37 | |||
38 | /** |
||
39 | * ShareFile Client. |
||
40 | * |
||
41 | * @var \Kapersoft\Sharefile\Client; |
||
42 | * */ |
||
43 | protected $client; |
||
44 | |||
45 | /** |
||
46 | * Indicated if metadata should include the ShareFile item array. |
||
47 | * |
||
48 | * @var bool |
||
49 | * */ |
||
50 | protected $returnShareFileItem; |
||
51 | |||
52 | /** |
||
53 | * SharefileAdapter constructor. |
||
54 | * |
||
55 | * @param Client $client Instance of Kapersoft\Sharefile\Client |
||
56 | * @param string $prefix Folder prefix |
||
57 | * @param bool $returnShareFileItem Indicated if getMetadatsa/listContents should return ShareFile item array. |
||
58 | * |
||
59 | * @param string $prefix |
||
60 | */ |
||
61 | 723 | public function __construct(Client $client, string $prefix = '', bool $returnShareFileItem = false) |
|
69 | |||
70 | /** |
||
71 | * {@inheritdoc} |
||
72 | */ |
||
73 | 240 | public function has($path) |
|
77 | |||
78 | /** |
||
79 | * {@inheritdoc} |
||
80 | */ |
||
81 | 60 | View Code Duplication | public function read($path) |
95 | |||
96 | /** |
||
97 | * {@inheritdoc} |
||
98 | */ |
||
99 | 60 | public function listContents($directory = '', $recursive = false) |
|
107 | |||
108 | /** |
||
109 | * {@inheritdoc} |
||
110 | */ |
||
111 | 540 | public function getMetadata($path) |
|
124 | |||
125 | /** |
||
126 | * {@inheritdoc} |
||
127 | */ |
||
128 | 60 | public function getSize($path) |
|
132 | |||
133 | /** |
||
134 | * {@inheritdoc} |
||
135 | */ |
||
136 | public function getMimetype($path) |
||
140 | |||
141 | /** |
||
142 | * {@inheritdoc} |
||
143 | */ |
||
144 | 60 | public function getTimestamp($path) |
|
148 | |||
149 | /** |
||
150 | * {@inheritdoc} |
||
151 | */ |
||
152 | 150 | public function write($path, $contents, Config $config = null) |
|
156 | |||
157 | /** |
||
158 | * {@inheritdoc} |
||
159 | */ |
||
160 | 150 | public function update($path, $contents, Config $config = null) |
|
164 | |||
165 | /** |
||
166 | * {@inheritdoc} |
||
167 | */ |
||
168 | 180 | public function rename($path, $newpath) |
|
194 | |||
195 | /** |
||
196 | * {@inheritdoc} |
||
197 | */ |
||
198 | 180 | public function copy($path, $newpath) |
|
222 | |||
223 | /** |
||
224 | * {@inheritdoc} |
||
225 | */ |
||
226 | 60 | public function delete($path) |
|
230 | |||
231 | /** |
||
232 | * {@inheritdoc} |
||
233 | */ |
||
234 | 60 | public function deleteDir($dirname) |
|
248 | |||
249 | /** |
||
250 | * {@inheritdoc} |
||
251 | */ |
||
252 | 120 | public function createDir($dirname, Config $config = null) |
|
269 | |||
270 | /** |
||
271 | * {@inheritdoc} |
||
272 | */ |
||
273 | 120 | public function put($path, $contents) |
|
277 | |||
278 | /** |
||
279 | * {@inheritdoc} |
||
280 | */ |
||
281 | 30 | View Code Duplication | public function readAndDelete($path) |
298 | |||
299 | /** |
||
300 | * Returns ShareFile client. |
||
301 | * |
||
302 | * @return Client |
||
303 | */ |
||
304 | 3 | public function getClient(): Client |
|
308 | |||
309 | /** |
||
310 | * Upload a file to ShareFile. |
||
311 | * |
||
312 | * @param string $path File path |
||
313 | * @param string $contents Contents of the file |
||
314 | * @param bool $overwrite Overwrite file is it exists |
||
315 | * |
||
316 | * @return array|false |
||
317 | */ |
||
318 | 240 | protected function uploadFile(string $path, string $contents, bool $overwrite = false) |
|
342 | |||
343 | /** |
||
344 | * Prepares upload-file. |
||
345 | * |
||
346 | * @param string $filename Filename |
||
347 | * @param string $contents Contents of the file |
||
348 | * |
||
349 | * @return string |
||
350 | */ |
||
351 | 150 | protected function prepareUploadFile(string $filename, string $contents):string |
|
360 | |||
361 | /** |
||
362 | * Removes temporary directory and upload-file. |
||
363 | * |
||
364 | * @param string $filename Filename. |
||
365 | */ |
||
366 | 150 | protected function removeUploadFile(string $filename) |
|
371 | |||
372 | /** |
||
373 | * Map ShareFile item to FlySystem metadata. |
||
374 | * |
||
375 | * @param array $item ShareFile item |
||
376 | * @param string $path Base path |
||
377 | * @param string|null $contents Contents of the file (optional) |
||
378 | * |
||
379 | * @return array |
||
380 | */ |
||
381 | 420 | protected function mapItemInfo(array $item, string $path = '', string $contents = null): array |
|
417 | |||
418 | /** |
||
419 | * Map list of ShareFile items with metadata. |
||
420 | * |
||
421 | * @param array $items List of ShareFile items |
||
422 | * @param string $path Base path |
||
423 | * |
||
424 | * @return array |
||
425 | */ |
||
426 | 30 | protected function mapItemList(array $items, string $path):array |
|
435 | |||
436 | /** |
||
437 | * Build metadata list from ShareFile item. |
||
438 | * |
||
439 | * @param array $item ShareFile item |
||
440 | * @param string $path Path of the given ShareFile item |
||
441 | * @param bool $recursive Recursive mode |
||
442 | * |
||
443 | * @return array |
||
444 | */ |
||
445 | 30 | protected function buildItemList(array $item, string $path, bool $recursive = false):array |
|
474 | |||
475 | /** |
||
476 | * Remove all items except files and folders in the given array of ShareFile items. |
||
477 | * |
||
478 | * @param array $items Array of ShareFile items |
||
479 | * |
||
480 | * @return array |
||
481 | */ |
||
482 | 30 | protected function removeAllExceptFilesAndFolders(array $items):array |
|
491 | |||
492 | /** |
||
493 | * Check if ShareFile item is a ShareFile.Api.Models.Folder type. |
||
494 | * |
||
495 | * @param array $item |
||
496 | * |
||
497 | * @return bool |
||
498 | */ |
||
499 | 570 | protected function isShareFileApiModelsFolder(array $item):bool |
|
503 | |||
504 | /** |
||
505 | * Check if ShareFile item is a ShareFile.Api.Models.File type. |
||
506 | * |
||
507 | * @param array $item |
||
508 | * |
||
509 | * @return bool |
||
510 | */ |
||
511 | 570 | protected function isShareFileApiModelsFile(array $item):bool |
|
515 | |||
516 | /** |
||
517 | * Get ShareFile item using path. |
||
518 | * |
||
519 | * @param string $path Path of the requested file |
||
520 | * |
||
521 | * @return array|false |
||
522 | * |
||
523 | * @throws Exception |
||
524 | */ |
||
525 | 720 | protected function getItemByPath(string $path) |
|
543 | |||
544 | /** |
||
545 | * Check access control of a ShareFile item. |
||
546 | * |
||
547 | * @param array $item ShareFile item |
||
548 | * @param string $rule Access rule |
||
549 | * |
||
550 | * @return bool |
||
551 | */ |
||
552 | 420 | protected function checkAccessControl(array $item, string $rule):bool |
|
567 | } |
||
568 |
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.