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 AwsS3 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 AwsS3, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
15 | class AwsS3 implements Adapter, MetadataSupporter, ListKeysAware, SizeCalculator, MimeTypeProvider |
||
16 | { |
||
17 | /* |
||
18 | * Amazon S3 does not not allow uploads > 5Go |
||
19 | */ |
||
20 | const MAX_CONTENT_SIZE = 5368709120; |
||
21 | const DEFAULT_PART_SIZE = 5242880; |
||
22 | |||
23 | /** @var S3Client */ |
||
24 | protected $service; |
||
25 | /** @var string */ |
||
26 | protected $bucket; |
||
27 | /** @var array */ |
||
28 | protected $options; |
||
29 | /** @var bool */ |
||
30 | protected $bucketExists; |
||
31 | /** @var array */ |
||
32 | protected $metadata = []; |
||
33 | /** @var bool */ |
||
34 | protected $detectContentType; |
||
35 | /** @var int */ |
||
36 | protected $sizeLimit = self::MAX_CONTENT_SIZE; |
||
37 | /** @var int */ |
||
38 | protected $partSize = self::DEFAULT_PART_SIZE; |
||
39 | |||
40 | /** |
||
41 | * @param S3Client $service |
||
42 | * @param string $bucket |
||
43 | * @param array $options |
||
44 | * @param bool $detectContentType |
||
45 | */ |
||
46 | public function __construct(S3Client $service, $bucket, array $options = [], $detectContentType = false) |
||
70 | |||
71 | /** |
||
72 | * Gets the publicly accessible URL of an Amazon S3 object. |
||
73 | * |
||
74 | * @param string $key Object key |
||
75 | * @param array $options Associative array of options used to buld the URL |
||
76 | * - expires: The time at which the URL should expire |
||
77 | * represented as a UNIX timestamp |
||
78 | * - Any options available in the Amazon S3 GetObject |
||
79 | * operation may be specified. |
||
80 | * |
||
81 | * @return string |
||
82 | * |
||
83 | * @deprecated 1.0 Resolving object path into URLs is out of the scope of this repository since v0.4. gaufrette/extras |
||
84 | * provides a Filesystem decorator with a regular resolve() method. You should use it instead. |
||
85 | * @see https://github.com/Gaufrette/extras |
||
86 | */ |
||
87 | public function getUrl($key, array $options = []) |
||
101 | |||
102 | /** |
||
103 | * {@inheritdoc} |
||
104 | */ |
||
105 | public function setMetadata($key, $metadata) |
||
115 | |||
116 | /** |
||
117 | * {@inheritdoc} |
||
118 | */ |
||
119 | public function getMetadata($key) |
||
123 | |||
124 | /** |
||
125 | * {@inheritdoc} |
||
126 | */ |
||
127 | public function read($key) |
||
147 | |||
148 | /** |
||
149 | * {@inheritdoc} |
||
150 | */ |
||
151 | public function rename($sourceKey, $targetKey) |
||
167 | |||
168 | /** |
||
169 | * {@inheritdoc} |
||
170 | */ |
||
171 | public function write($key, $content) |
||
210 | |||
211 | /** |
||
212 | * {@inheritdoc} |
||
213 | */ |
||
214 | public function exists($key) |
||
218 | |||
219 | /** |
||
220 | * {@inheritdoc} |
||
221 | */ |
||
222 | View Code Duplication | public function mtime($key) |
|
232 | |||
233 | /** |
||
234 | * {@inheritdoc} |
||
235 | */ |
||
236 | View Code Duplication | public function size($key) |
|
246 | |||
247 | /** |
||
248 | * {@inheritdoc} |
||
249 | */ |
||
250 | public function keys() |
||
254 | |||
255 | /** |
||
256 | * {@inheritdoc} |
||
257 | */ |
||
258 | public function listKeys($prefix = '') |
||
277 | |||
278 | /** |
||
279 | * {@inheritdoc} |
||
280 | */ |
||
281 | public function delete($key) |
||
291 | |||
292 | /** |
||
293 | * {@inheritdoc} |
||
294 | */ |
||
295 | public function isDirectory($key) |
||
310 | |||
311 | /** |
||
312 | * Ensures the specified bucket exists. If the bucket does not exists |
||
313 | * and the create option is set to true, it will try to create the |
||
314 | * bucket. The bucket is created using the same region as the supplied |
||
315 | * client object. |
||
316 | * |
||
317 | * @throws \RuntimeException if the bucket does not exists or could not be |
||
318 | * created |
||
319 | */ |
||
320 | protected function ensureBucketExists() |
||
342 | |||
343 | protected function getOptions($key, array $options = []) |
||
357 | |||
358 | View Code Duplication | protected function computePath($key) |
|
366 | |||
367 | /** |
||
368 | * MultiPart upload for big files (exceeding size_limit) |
||
369 | * |
||
370 | * @param string $key |
||
371 | * @param resource $content |
||
372 | * |
||
373 | * @return bool |
||
374 | */ |
||
375 | protected function multipartUpload($key, $content) |
||
402 | |||
403 | /** |
||
404 | * @param string $key |
||
405 | * |
||
406 | * @return string |
||
407 | */ |
||
408 | protected function initiateMultipartUpload($key) |
||
415 | |||
416 | /** |
||
417 | * @param string $key |
||
418 | * @param string $content |
||
419 | * @param string $uploadId |
||
420 | * @param int $partNumber |
||
421 | * |
||
422 | * @return \Aws\Result |
||
423 | */ |
||
424 | protected function uploadNextPart($key, $content, $uploadId, $partNumber) |
||
439 | |||
440 | /** |
||
441 | * @param string $key |
||
442 | * @param string $uploadId |
||
443 | * @param array $parts |
||
444 | */ |
||
445 | protected function completeMultipartUpload($key, $uploadId, $parts) |
||
456 | |||
457 | /** |
||
458 | * @param string $key |
||
459 | * @param string $uploadId |
||
460 | */ |
||
461 | protected function abortMultipartUpload($key, $uploadId) |
||
466 | |||
467 | /** |
||
468 | * Computes the key from the specified path. |
||
469 | * |
||
470 | * @param string $path |
||
471 | * |
||
472 | * @return string |
||
473 | */ |
||
474 | protected function computeKey($path) |
||
478 | |||
479 | /** |
||
480 | * @param string $content |
||
481 | * |
||
482 | * @return string |
||
483 | */ |
||
484 | View Code Duplication | private function guessContentType($content) |
|
494 | |||
495 | /** |
||
496 | * @param string $key |
||
497 | * |
||
498 | * @return string |
||
499 | */ |
||
500 | View Code Duplication | public function mimeType($key) |
|
510 | } |
||
511 |
If you suppress an error, we recommend checking for the error condition explicitly: