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 DBFile 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 DBFile, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
20 | |||
21 | /** |
||
22 | * Represents a file reference stored in a database |
||
23 | * |
||
24 | * @property string $Hash SHA of the file |
||
25 | * @property string $Filename Name of the file, including directory |
||
26 | * @property string $Variant Variant of the file |
||
27 | * |
||
28 | * @package framework |
||
29 | * @subpackage filesystem |
||
30 | */ |
||
31 | class DBFile extends DBComposite implements AssetContainer, ShortcodeHandler { |
||
32 | |||
33 | use ImageManipulation; |
||
34 | |||
35 | /** |
||
36 | * List of allowed file categories. |
||
37 | * |
||
38 | * {@see File::$app_categories} |
||
39 | * |
||
40 | * @var array |
||
41 | */ |
||
42 | protected $allowedCategories = array(); |
||
43 | |||
44 | /** |
||
45 | * List of image mime types supported by the image manipulations API |
||
46 | * |
||
47 | * {@see File::app_categories} for matching extensions. |
||
48 | * |
||
49 | * @config |
||
50 | * @var array |
||
51 | */ |
||
52 | private static $supported_images = array( |
||
53 | 'image/jpeg', |
||
54 | 'image/gif', |
||
55 | 'image/png' |
||
56 | ); |
||
57 | |||
58 | /** |
||
59 | * Create a new image manipulation |
||
60 | * |
||
61 | * @param string $name |
||
62 | * @param array|string $allowed List of allowed file categories (not extensions), as per File::$app_categories |
||
63 | */ |
||
64 | public function __construct($name = null, $allowed = array()) { |
||
68 | |||
69 | /** |
||
70 | * Determine if a valid non-empty image exists behind this asset, which is a format |
||
71 | * compatible with image manipulations |
||
72 | * |
||
73 | * @return boolean |
||
74 | */ |
||
75 | public function getIsImage() { |
||
80 | |||
81 | /** |
||
82 | * @return AssetStore |
||
83 | */ |
||
84 | protected function getStore() { |
||
87 | |||
88 | private static $composite_db = array( |
||
89 | "Hash" => "Varchar(255)", // SHA of the base content |
||
90 | "Filename" => "Varchar(255)", // Path identifier of the base content |
||
91 | "Variant" => "Varchar(255)", // Identifier of the variant to the base, if given |
||
92 | ); |
||
93 | |||
94 | private static $casting = array( |
||
95 | 'URL' => 'Varchar', |
||
96 | 'AbsoluteURL' => 'Varchar', |
||
97 | 'Basename' => 'Varchar', |
||
98 | 'Title' => 'Varchar', |
||
99 | 'MimeType' => 'Varchar', |
||
100 | 'String' => 'Text', |
||
101 | 'Tag' => 'HTMLText', |
||
102 | 'Size' => 'Varchar' |
||
103 | ); |
||
104 | |||
105 | public function scaffoldFormField($title = null, $params = null) { |
||
108 | |||
109 | /** |
||
110 | * Return a html5 tag of the appropriate for this file (normally img or a) |
||
111 | * |
||
112 | * @return string |
||
113 | */ |
||
114 | public function forTemplate() { |
||
117 | |||
118 | /** |
||
119 | * Return a html5 tag of the appropriate for this file (normally img or a) |
||
120 | * |
||
121 | * @return string |
||
122 | */ |
||
123 | public function getTag() { |
||
130 | |||
131 | /** |
||
132 | * Determine the template to render as on the frontend |
||
133 | * |
||
134 | * @return string Name of template |
||
135 | */ |
||
136 | public function getFrontendTemplate() { |
||
151 | |||
152 | /** |
||
153 | * Get trailing part of filename |
||
154 | * |
||
155 | * @return string |
||
156 | */ |
||
157 | public function getBasename() { |
||
162 | |||
163 | /** |
||
164 | * Get file extension |
||
165 | * |
||
166 | * @return string |
||
167 | */ |
||
168 | public function getExtension() { |
||
173 | |||
174 | /** |
||
175 | * Alt title for this |
||
176 | * |
||
177 | * @return string |
||
178 | */ |
||
179 | public function getTitle() { |
||
187 | |||
188 | View Code Duplication | public function setFromLocalFile($path, $filename = null, $hash = null, $variant = null, $conflictResolution = null) { |
|
199 | |||
200 | View Code Duplication | public function setFromStream($stream, $filename, $hash = null, $variant = null, $conflictResolution = null) { |
|
211 | |||
212 | View Code Duplication | public function setFromString($data, $filename, $hash = null, $variant = null, $conflictResolution = null) { |
|
223 | |||
224 | View Code Duplication | public function getStream() { |
|
232 | |||
233 | View Code Duplication | public function getString() { |
|
241 | |||
242 | public function getURL() { |
||
251 | |||
252 | /** |
||
253 | * Get URL, but without resampling. |
||
254 | * Note that this will return the url even if the file does not exist. |
||
255 | * |
||
256 | * @return string |
||
257 | */ |
||
258 | public function getSourceURL() { |
||
263 | |||
264 | /** |
||
265 | * Get the absolute URL to this resource |
||
266 | * |
||
267 | * @return type |
||
268 | */ |
||
269 | public function getAbsoluteURL() { |
||
275 | |||
276 | View Code Duplication | public function getMetaData() { |
|
284 | |||
285 | View Code Duplication | public function getMimeType() { |
|
293 | |||
294 | public function getValue() { |
||
303 | |||
304 | View Code Duplication | public function exists() { |
|
312 | |||
313 | public static function get_shortcodes() { |
||
316 | |||
317 | public static function handle_shortcode($arguments, $content, $parser, $shortcode, $extra = array()) { |
||
320 | |||
321 | public function getFilename() { |
||
324 | |||
325 | public function getHash() { |
||
328 | |||
329 | public function getVariant() { |
||
332 | |||
333 | /** |
||
334 | * Return file size in bytes. |
||
335 | * |
||
336 | * @return int |
||
337 | */ |
||
338 | public function getAbsoluteSize() { |
||
344 | |||
345 | /** |
||
346 | * Customise this object with an "original" record for getting other customised fields |
||
347 | * |
||
348 | * @param AssetContainer $original |
||
349 | * @return $this |
||
350 | */ |
||
351 | public function setOriginal($original) { |
||
355 | |||
356 | /** |
||
357 | * Get list of allowed file categories |
||
358 | * |
||
359 | * @return array |
||
360 | */ |
||
361 | public function getAllowedCategories() { |
||
364 | |||
365 | /** |
||
366 | * Assign allowed categories |
||
367 | * |
||
368 | * @param array|string $categories |
||
369 | * @return $this |
||
370 | */ |
||
371 | public function setAllowedCategories($categories) { |
||
378 | |||
379 | /** |
||
380 | * Gets the list of extensions (if limited) for this field. Empty list |
||
381 | * means there is no restriction on allowed types. |
||
382 | * |
||
383 | * @return array |
||
384 | */ |
||
385 | protected function getAllowedExtensions() { |
||
389 | |||
390 | /** |
||
391 | * Validate that this DBFile accepts this filename as valid |
||
392 | * |
||
393 | * @param string $filename |
||
394 | * @throws ValidationException |
||
395 | * @return bool |
||
396 | */ |
||
397 | protected function isValidFilename($filename) { |
||
415 | |||
416 | /** |
||
417 | * Check filename, and raise a ValidationException if invalid |
||
418 | * |
||
419 | * @param string $filename |
||
420 | * @throws ValidationException |
||
421 | */ |
||
422 | protected function assertFilenameValid($filename) { |
||
429 | |||
430 | |||
431 | /** |
||
432 | * Hook to validate this record against a validation result |
||
433 | * |
||
434 | * @param ValidationResult $result |
||
435 | * @param string $filename Optional filename to validate. If omitted, the current value is validated. |
||
436 | * @return bool Valid flag |
||
437 | */ |
||
438 | public function validate(ValidationResult $result, $filename = null) { |
||
461 | |||
462 | public function setField($field, $value, $markChanged = true) { |
||
470 | |||
471 | |||
472 | /** |
||
473 | * Returns the size of the file type in an appropriate format. |
||
474 | * |
||
485 |
In PHP, under loose comparison (like
==
, or!=
, orswitch
conditions), values of different types might be equal.For
string
values, the empty string''
is a special case, in particular the following results might be unexpected: