Complex classes like AssetField 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 AssetField, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 29 | class AssetField extends FormField |
||
| 30 | { |
||
| 31 | use UploadReceiver; |
||
| 32 | |||
| 33 | /** |
||
| 34 | * @var array |
||
| 35 | */ |
||
| 36 | private static $allowed_actions = array( |
||
| 37 | 'upload' |
||
| 38 | ); |
||
| 39 | |||
| 40 | /** |
||
| 41 | * @var array |
||
| 42 | */ |
||
| 43 | private static $url_handlers = array( |
||
| 44 | '$Action!' => '$Action', |
||
| 45 | ); |
||
| 46 | |||
| 47 | private static $casting = array( |
||
| 48 | 'Value' => 'DBFile', |
||
| 49 | 'UploadFieldThumbnailURL' => 'Varchar' |
||
| 50 | ); |
||
| 51 | |||
| 52 | /** |
||
| 53 | * Template to use for the file button widget |
||
| 54 | * |
||
| 55 | * @var string |
||
| 56 | */ |
||
| 57 | protected $templateFileButtons = null; |
||
| 58 | |||
| 59 | /** |
||
| 60 | * Parent data record. Will be infered from parent form or controller if blank. The destination |
||
| 61 | * DBFile should be a property of the name $name on this object. |
||
| 62 | * |
||
| 63 | * @var DataObject |
||
| 64 | */ |
||
| 65 | protected $record; |
||
| 66 | |||
| 67 | /** |
||
| 68 | * Config for this field used in the front-end javascript |
||
| 69 | * (will be merged into the config of the javascript file upload plugin). |
||
| 70 | * |
||
| 71 | * @var array |
||
| 72 | */ |
||
| 73 | protected $ufConfig = array(); |
||
| 74 | |||
| 75 | /** |
||
| 76 | * Front end config defaults |
||
| 77 | * |
||
| 78 | * @config |
||
| 79 | * @var array |
||
| 80 | */ |
||
| 81 | private static $defaultConfig = array( |
||
| 82 | /** |
||
| 83 | * Automatically upload the file once selected |
||
| 84 | * |
||
| 85 | * @var boolean |
||
| 86 | */ |
||
| 87 | 'autoUpload' => true, |
||
| 88 | |||
| 89 | /** |
||
| 90 | * Can the user upload new files. |
||
| 91 | * String values are interpreted as permission codes. |
||
| 92 | * |
||
| 93 | * @var boolean|string |
||
| 94 | */ |
||
| 95 | 'canUpload' => true, |
||
| 96 | |||
| 97 | /** |
||
| 98 | * Shows the target folder for new uploads in the field UI. |
||
| 99 | * Disable to keep the internal filesystem structure hidden from users. |
||
| 100 | * |
||
| 101 | * @var boolean|string |
||
| 102 | */ |
||
| 103 | 'canPreviewFolder' => true, |
||
| 104 | |||
| 105 | /** |
||
| 106 | * Indicate a change event to the containing form if an upload |
||
| 107 | * or file edit/delete was performed. |
||
| 108 | * |
||
| 109 | * @var boolean |
||
| 110 | */ |
||
| 111 | 'changeDetection' => true, |
||
| 112 | |||
| 113 | /** |
||
| 114 | * Maximum width of the preview thumbnail |
||
| 115 | * |
||
| 116 | * @var integer |
||
| 117 | */ |
||
| 118 | 'previewMaxWidth' => 80, |
||
| 119 | |||
| 120 | /** |
||
| 121 | * Maximum height of the preview thumbnail |
||
| 122 | * |
||
| 123 | * @var integer |
||
| 124 | */ |
||
| 125 | 'previewMaxHeight' => 60, |
||
| 126 | |||
| 127 | /** |
||
| 128 | * javascript template used to display uploading files |
||
| 129 | * |
||
| 130 | * @see javascript/UploadField_uploadtemplate.js |
||
| 131 | * @var string |
||
| 132 | */ |
||
| 133 | 'uploadTemplateName' => 'ss-uploadfield-uploadtemplate', |
||
| 134 | |||
| 135 | /** |
||
| 136 | * javascript template used to display already uploaded files |
||
| 137 | * |
||
| 138 | * @see javascript/UploadField_downloadtemplate.js |
||
| 139 | * @var string |
||
| 140 | */ |
||
| 141 | 'downloadTemplateName' => 'ss-uploadfield-downloadtemplate' |
||
| 142 | ); |
||
| 143 | |||
| 144 | /** |
||
| 145 | * Folder to display in "Select files" list. |
||
| 146 | * Defaults to listing all files regardless of folder. |
||
| 147 | * The folder path should be relative to the webroot. |
||
| 148 | * See {@link FileField->folderName} to set the upload target instead. |
||
| 149 | * |
||
| 150 | * @var string |
||
| 151 | * @example admin/folder/subfolder |
||
| 152 | */ |
||
| 153 | protected $displayFolderName; |
||
| 154 | |||
| 155 | /** |
||
| 156 | * Construct a new UploadField instance |
||
| 157 | * |
||
| 158 | * @param string $name The internal field name, passed to forms. |
||
| 159 | * @param string $title The field label. |
||
| 160 | */ |
||
| 161 | public function __construct($name, $title = null) |
||
| 184 | |||
| 185 | /** |
||
| 186 | * Set name of template used for Buttons on each file (replace, edit, remove, delete) (without path or extension) |
||
| 187 | * |
||
| 188 | * @param string |
||
| 189 | * @return $this |
||
| 190 | */ |
||
| 191 | public function setTemplateFileButtons($template) |
||
| 196 | |||
| 197 | /** |
||
| 198 | * @return string |
||
| 199 | */ |
||
| 200 | public function getTemplateFileButtons() |
||
| 204 | |||
| 205 | /** |
||
| 206 | * Determine if the target folder for new uploads in is visible the field UI. |
||
| 207 | * |
||
| 208 | * @return boolean |
||
| 209 | */ |
||
| 210 | public function canPreviewFolder() |
||
| 221 | |||
| 222 | /** |
||
| 223 | * Determine if the target folder for new uploads in is visible the field UI. |
||
| 224 | * Disable to keep the internal filesystem structure hidden from users. |
||
| 225 | * |
||
| 226 | * @param boolean|string $canPreviewFolder Either a boolean flag, or a |
||
| 227 | * required permission code |
||
| 228 | * @return $this Self reference |
||
| 229 | */ |
||
| 230 | public function setCanPreviewFolder($canPreviewFolder) |
||
| 234 | |||
| 235 | /** |
||
| 236 | * @param string |
||
| 237 | * @return $this |
||
| 238 | */ |
||
| 239 | public function setDisplayFolderName($name) |
||
| 244 | |||
| 245 | /** |
||
| 246 | * @return string |
||
| 247 | */ |
||
| 248 | public function getDisplayFolderName() |
||
| 252 | |||
| 253 | /** |
||
| 254 | * Force a record to be used as "Parent" for uploaded Files (eg a Page with a has_one to File) |
||
| 255 | * |
||
| 256 | * @param DataObject $record |
||
| 257 | * @return $this |
||
| 258 | */ |
||
| 259 | public function setRecord($record) |
||
| 264 | |||
| 265 | /** |
||
| 266 | * Get the record to use as "Parent" for uploaded Files (eg a Page with a has_one to File) If none is set, it will |
||
| 267 | * use Form->getRecord(). |
||
| 268 | * |
||
| 269 | * @return DataObject |
||
| 270 | */ |
||
| 271 | public function getRecord() |
||
| 282 | |||
| 283 | public function setValue($value, $record = null) |
||
| 318 | |||
| 319 | public function Value() |
||
| 324 | |||
| 325 | public function saveInto(DataObjectInterface $record) |
||
| 341 | |||
| 342 | /** |
||
| 343 | * Assign a front-end config variable for the upload field |
||
| 344 | * |
||
| 345 | * @see https://github.com/blueimp/jQuery-File-Upload/wiki/Options for the list of front end options available |
||
| 346 | * |
||
| 347 | * @param string $key |
||
| 348 | * @param mixed $val |
||
| 349 | * @return $this self reference |
||
| 350 | */ |
||
| 351 | public function setConfig($key, $val) |
||
| 356 | |||
| 357 | /** |
||
| 358 | * Gets a front-end config variable for the upload field |
||
| 359 | * |
||
| 360 | * @see https://github.com/blueimp/jQuery-File-Upload/wiki/Options for the list of front end options available |
||
| 361 | * |
||
| 362 | * @param string $key |
||
| 363 | * @return mixed |
||
| 364 | */ |
||
| 365 | public function getConfig($key) |
||
| 371 | |||
| 372 | /** |
||
| 373 | * Determine if the field should automatically upload the file. |
||
| 374 | * |
||
| 375 | * @return boolean |
||
| 376 | */ |
||
| 377 | public function getAutoUpload() |
||
| 381 | |||
| 382 | /** |
||
| 383 | * Determine if the field should automatically upload the file |
||
| 384 | * |
||
| 385 | * @param boolean $autoUpload |
||
| 386 | * @return $this Self reference |
||
| 387 | */ |
||
| 388 | public function setAutoUpload($autoUpload) |
||
| 392 | |||
| 393 | /** |
||
| 394 | * Determine if the user has permission to upload. |
||
| 395 | * |
||
| 396 | * @return boolean |
||
| 397 | */ |
||
| 398 | public function canUpload() |
||
| 409 | |||
| 410 | /** |
||
| 411 | * Specify whether the user can upload files. |
||
| 412 | * String values will be treated as required permission codes |
||
| 413 | * |
||
| 414 | * @param bool|string $canUpload Either a boolean flag, or a required |
||
| 415 | * permission code |
||
| 416 | * @return $this Self reference |
||
| 417 | */ |
||
| 418 | public function setCanUpload($canUpload) |
||
| 422 | |||
| 423 | /** |
||
| 424 | * Returns true if the field is neither readonly nor disabled |
||
| 425 | * |
||
| 426 | * @return bool |
||
| 427 | */ |
||
| 428 | public function isActive() |
||
| 432 | |||
| 433 | /** |
||
| 434 | * Gets thumbnail width. Defaults to 80 |
||
| 435 | * |
||
| 436 | * @return int |
||
| 437 | */ |
||
| 438 | public function getPreviewMaxWidth() |
||
| 442 | |||
| 443 | /** |
||
| 444 | * Set thumbnail width. |
||
| 445 | * |
||
| 446 | * @param int $previewMaxWidth |
||
| 447 | * @return $this Self reference |
||
| 448 | */ |
||
| 449 | public function setPreviewMaxWidth($previewMaxWidth) |
||
| 453 | |||
| 454 | /** |
||
| 455 | * Gets thumbnail height. Defaults to 60 |
||
| 456 | * |
||
| 457 | * @return int |
||
| 458 | */ |
||
| 459 | public function getPreviewMaxHeight() |
||
| 463 | |||
| 464 | /** |
||
| 465 | * Set thumbnail height. |
||
| 466 | * |
||
| 467 | * @param int $previewMaxHeight |
||
| 468 | * @return $this Self reference |
||
| 469 | */ |
||
| 470 | public function setPreviewMaxHeight($previewMaxHeight) |
||
| 474 | |||
| 475 | /** |
||
| 476 | * javascript template used to display uploading files |
||
| 477 | * Defaults to 'ss-uploadfield-uploadtemplate' |
||
| 478 | * |
||
| 479 | * @see javascript/UploadField_uploadtemplate.js |
||
| 480 | * @return string |
||
| 481 | */ |
||
| 482 | public function getUploadTemplateName() |
||
| 486 | |||
| 487 | /** |
||
| 488 | * Set javascript template used to display uploading files |
||
| 489 | * |
||
| 490 | * @param string $uploadTemplateName |
||
| 491 | * @return $this Self reference |
||
| 492 | */ |
||
| 493 | public function setUploadTemplateName($uploadTemplateName) |
||
| 497 | |||
| 498 | /** |
||
| 499 | * javascript template used to display already uploaded files |
||
| 500 | * Defaults to 'ss-downloadfield-downloadtemplate' |
||
| 501 | * |
||
| 502 | * @see javascript/DownloadField_downloadtemplate.js |
||
| 503 | * @return string |
||
| 504 | */ |
||
| 505 | public function getDownloadTemplateName() |
||
| 509 | |||
| 510 | /** |
||
| 511 | * Set javascript template used to display already uploaded files |
||
| 512 | * |
||
| 513 | * @param string $downloadTemplateName |
||
| 514 | * @return $this Self reference |
||
| 515 | */ |
||
| 516 | public function setDownloadTemplateName($downloadTemplateName) |
||
| 520 | |||
| 521 | public function extraClass() |
||
| 532 | |||
| 533 | public function Field($properties = array()) |
||
| 573 | |||
| 574 | /** |
||
| 575 | * Validation method for this field, called when the entire form is validated |
||
| 576 | * |
||
| 577 | * @param Validator $validator |
||
| 578 | * @return boolean |
||
| 579 | */ |
||
| 580 | public function validate($validator) |
||
| 616 | |||
| 617 | /** |
||
| 618 | * Given an array of post variables, extract all temporary file data into an array |
||
| 619 | * |
||
| 620 | * @param array $postVars Array of posted form data |
||
| 621 | * @return array data for uploaded file |
||
| 622 | */ |
||
| 623 | protected function extractUploadedFileData($postVars) |
||
| 647 | |||
| 648 | /** |
||
| 649 | * Loads the temporary file data into the asset store, and return the tuple details |
||
| 650 | * for the result. |
||
| 651 | * |
||
| 652 | * @param array $tmpFile Temporary file data |
||
| 653 | * @param string $error Error message |
||
| 654 | * @return array Result of saved file, or null if error |
||
| 655 | */ |
||
| 656 | protected function saveTemporaryFile($tmpFile, &$error = null) |
||
| 689 | |||
| 690 | /** |
||
| 691 | * Safely encodes the File object with all standard fields required |
||
| 692 | * by the front end |
||
| 693 | * |
||
| 694 | * @param string $filename |
||
| 695 | * @param string $hash |
||
| 696 | * @param string $variant |
||
| 697 | * @return array Encoded list of file attributes |
||
| 698 | */ |
||
| 699 | protected function encodeAssetAttributes($filename, $hash, $variant) |
||
| 721 | |||
| 722 | /** |
||
| 723 | * Action to handle upload of a single file |
||
| 724 | * |
||
| 725 | * @param HTTPRequest $request |
||
| 726 | * @return HTTPResponse |
||
| 727 | */ |
||
| 728 | public function upload(HTTPRequest $request) |
||
| 769 | |||
| 770 | public function performReadonlyTransformation() |
||
| 777 | |||
| 778 | /** |
||
| 779 | * Gets the foreign class that needs to be created, or 'File' as default if there |
||
| 780 | * is no relationship, or it cannot be determined. |
||
| 781 | * |
||
| 782 | * @param string $default Default value to return if no value could be calculated |
||
| 783 | * @return string Foreign class name. |
||
| 784 | */ |
||
| 785 | public function getRelationAutosetClass($default = 'SilverStripe\\Assets\\File') |
||
| 803 | |||
| 804 | /** |
||
| 805 | * @return AssetStore |
||
| 806 | */ |
||
| 807 | protected function getAssetStore() |
||
| 811 | |||
| 812 | public function getAttributes() |
||
| 819 | } |
||
| 820 |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignorePhpDoc annotation to the duplicate definition and it will be ignored.