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 Folder 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 Folder, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
36 | class Folder extends AbstractFileableCmisObject implements FolderInterface |
||
37 | { |
||
38 | /** |
||
39 | * Creates a new document in this folder. |
||
40 | * |
||
41 | * @param array $properties The property values that MUST be applied to the object. The array key is the property |
||
42 | * name the value is the property value. |
||
43 | * @param StreamInterface $contentStream |
||
44 | * @param VersioningState $versioningState An enumeration specifying what the versioning state of the newly-created |
||
45 | * object MUST be. Valid values are: |
||
46 | * <code>none</code> |
||
47 | * (default, if the object-type is not versionable) The document MUST be created as a non-versionable |
||
48 | * document. |
||
49 | * <code>checkedout</code> |
||
50 | * The document MUST be created in the checked-out state. The checked-out document MAY be |
||
51 | * visible to other users. |
||
52 | * <code>major</code> |
||
53 | * (default, if the object-type is versionable) The document MUST be created as a major version. |
||
54 | * <code>minor</code> |
||
55 | * The document MUST be created as a minor version. |
||
56 | * @param PolicyInterface[] $policies A list of policy ids that MUST be applied to the newly-created document |
||
57 | * object. |
||
58 | * @param AceInterface[] $addAces A list of ACEs that MUST be added to the newly-created document object, either |
||
59 | * using the ACL from folderId if specified, or being applied if no folderId is specified. |
||
60 | * @param AceInterface[] $removeAces A list of ACEs that MUST be removed from the newly-created document object, |
||
61 | * either using the ACL from folderId if specified, or being ignored if no folderId is specified. |
||
62 | * @param OperationContextInterface|null $context |
||
63 | * @return DocumentInterface|null the new folder object or <code>null</code> if the parameter <code>context</code> |
||
64 | * was set to <code>null</code> |
||
65 | * @throws CmisRuntimeException Exception is thrown if the created object is not a document |
||
66 | */ |
||
67 | View Code Duplication | public function createDocument( |
|
96 | |||
97 | /** |
||
98 | * Creates a new document from a source document in this folder. |
||
99 | * |
||
100 | * @param ObjectIdInterface $source The ID of the source document. |
||
101 | * @param array $properties The property values that MUST be applied to the object. The array key is the property |
||
102 | * name the value is the property value. |
||
103 | * @param VersioningState $versioningState An enumeration specifying what the versioning state of the newly-created |
||
104 | * object MUST be. Valid values are: |
||
105 | * <code>none</code> |
||
106 | * (default, if the object-type is not versionable) The document MUST be created as a non-versionable |
||
107 | * document. |
||
108 | * <code>checkedout</code> |
||
109 | * The document MUST be created in the checked-out state. The checked-out document MAY be |
||
110 | * visible to other users. |
||
111 | * <code>major</code> |
||
112 | * (default, if the object-type is versionable) The document MUST be created as a major version. |
||
113 | * <code>minor</code> |
||
114 | * The document MUST be created as a minor version. |
||
115 | * @param PolicyInterface[] $policies A list of policy ids that MUST be applied to the newly-created document |
||
116 | * object. |
||
117 | * @param AceInterface[] $addAces A list of ACEs that MUST be added to the newly-created document object, either |
||
118 | * using the ACL from folderId if specified, or being applied if no folderId is specified. |
||
119 | * @param AceInterface[] $removeAces A list of ACEs that MUST be removed from the newly-created document object, |
||
120 | * either using the ACL from folderId if specified, or being ignored if no folderId is specified. |
||
121 | * @param OperationContextInterface|null $context |
||
122 | * @return DocumentInterface|null the new folder object or <code>null</code> if the parameter <code>context</code> |
||
123 | * was set to <code>null</code> |
||
124 | * @throws CmisRuntimeException Exception is thrown if the created object is not a document |
||
125 | */ |
||
126 | View Code Duplication | public function createDocumentFromSource( |
|
155 | |||
156 | /** |
||
157 | * Creates a new subfolder in this folder. |
||
158 | * |
||
159 | * @param array $properties The property values that MUST be applied to the newly-created item object. |
||
160 | * @param PolicyInterface[] $policies A list of policy ids that MUST be applied to the newly-created folder object. |
||
161 | * @param AceInterface[] $addAces A list of ACEs that MUST be added to the newly-created folder object, either |
||
162 | * using the ACL from folderId if specified, or being applied if no folderId is specified. |
||
163 | * @param AceInterface[] $removeAces A list of ACEs that MUST be removed from the newly-created folder object, |
||
164 | * either using the ACL from folderId if specified, or being ignored if no folderId is specified. |
||
165 | * @param OperationContextInterface|null $context |
||
166 | * @return FolderInterface|null the new folder object or <code>null</code> if the parameter <code>context</code> |
||
167 | * was set to <code>null</code> |
||
168 | * @throws CmisRuntimeException Exception is thrown if the created object is not a folder |
||
169 | */ |
||
170 | View Code Duplication | public function createFolder( |
|
189 | |||
190 | /** |
||
191 | * Creates a new item in this folder. |
||
192 | * |
||
193 | * @param array $properties The property values that MUST be applied to the newly-created item object. |
||
194 | * @param PolicyInterface[] $policies A list of policy ids that MUST be applied to the newly-created item object. |
||
195 | * @param AceInterface[] $addAces A list of ACEs that MUST be added to the newly-created item object, either using |
||
196 | * the ACL from folderId if specified, or being applied if no folderId is specified. |
||
197 | * @param AceInterface[] $removeAces A list of ACEs that MUST be removed from the newly-created item object, either |
||
198 | * using the ACL from folderId if specified, or being ignored if no folderId is specified. |
||
199 | * @param OperationContextInterface|null $context |
||
200 | * @return ItemInterface|null the new item object |
||
201 | * @throws CmisRuntimeException Exception is thrown if the created object is not a item |
||
202 | */ |
||
203 | View Code Duplication | public function createItem( |
|
222 | |||
223 | /** |
||
224 | * Creates a new policy in this folder. |
||
225 | * |
||
226 | * @param array $properties The property values that MUST be applied to the newly-created policy object. |
||
227 | * @param PolicyInterface[] $policies A list of policy ids that MUST be applied to the newly-created policy object. |
||
228 | * @param AceInterface[] $addAces A list of ACEs that MUST be added to the newly-created policy object, either |
||
229 | * using the ACL from folderId if specified, or being applied if no folderId is specified. |
||
230 | * @param AceInterface[] $removeAces A list of ACEs that MUST be removed from the newly-created policy object, |
||
231 | * either using the ACL from folderId if specified, or being ignored if no folderId is specified. |
||
232 | * @param OperationContextInterface|null $context |
||
233 | * @return PolicyInterface|null the new policy object |
||
234 | * @throws CmisRuntimeException Exception is thrown if the created object is not a policy |
||
235 | */ |
||
236 | View Code Duplication | public function createPolicy( |
|
255 | |||
256 | /** |
||
257 | * Deletes this folder and all subfolders. |
||
258 | * |
||
259 | * @param boolean $allVersions If <code>true</code>, then delete all versions of all documents. If |
||
260 | * <code>false</code>, delete only the document versions referenced in the tree. The repository MUST ignore the |
||
261 | * value of this parameter when this service is invoked on any non-document objects or non-versionable document |
||
262 | * objects. |
||
263 | * @param UnfileObject $unfile An enumeration specifying how the repository MUST process file-able child- or |
||
264 | * descendant-objects. |
||
265 | * @param boolean $continueOnFailure If <code>true</code>, then the repository SHOULD continue attempting to |
||
266 | * perform this operation even if deletion of a child- or descendant-object in the specified folder cannot be |
||
267 | * deleted. If <code>false</code>, then the repository SHOULD abort this method when it fails to |
||
268 | * delete a single child object or descendant object. |
||
269 | * @return FailedToDeleteDataInterface A list of identifiers of objects in the folder tree that were not deleted. |
||
270 | */ |
||
271 | public function deleteTree($allVersions, UnfileObject $unfile, $continueOnFailure = true) |
||
287 | |||
288 | /** |
||
289 | * Returns all checked out documents in this folder using the given OperationContext. |
||
290 | * |
||
291 | * @param OperationContextInterface|null $context |
||
292 | * @return DocumentInterface[] A list of checked out documents. |
||
293 | */ |
||
294 | public function getCheckedOutDocs(OperationContextInterface $context = null) |
||
321 | |||
322 | /** |
||
323 | * Returns the children of this folder using the given OperationContext. |
||
324 | * |
||
325 | * @param OperationContextInterface|null $context |
||
326 | * @return CmisObjectInterface[] A list of the child objects for the specified folder. |
||
327 | */ |
||
328 | public function getChildren(OperationContextInterface $context = null) |
||
352 | |||
353 | /** |
||
354 | * Gets the folder descendants starting with this folder. |
||
355 | * |
||
356 | * @param integer $depth |
||
357 | * @param OperationContextInterface|null $context |
||
358 | * @return TreeInterface A tree that contains FileableCmisObject objects |
||
359 | * @see FileableCmisObject FileableCmisObject contained in returned TreeInterface |
||
360 | */ |
||
361 | View Code Duplication | public function getDescendants($depth, OperationContextInterface $context = null) |
|
377 | |||
378 | /** |
||
379 | * Gets the parent folder object. |
||
380 | * |
||
381 | * @return FolderInterface|null the parent folder object or <code>null</code> if the folder is the root folder. |
||
382 | */ |
||
383 | public function getFolderParent() |
||
400 | |||
401 | /** |
||
402 | * Gets the folder tree starting with this folder using the given OperationContext. |
||
403 | * |
||
404 | * @param integer $depth The number of levels of depth in the folder hierarchy from which to return results. |
||
405 | * Valid values are: |
||
406 | * 1 |
||
407 | * Return only objects that are children of the folder. See also getChildren. |
||
408 | * <Integer value greater than 1> |
||
409 | * Return only objects that are children of the folder and descendants up to <value> levels deep. |
||
410 | * -1 |
||
411 | * Return ALL descendant objects at all depth levels in the CMIS hierarchy. |
||
412 | * The default value is repository specific and SHOULD be at least 2 or -1. |
||
413 | * @param OperationContextInterface|null $context |
||
414 | * @return TreeInterface A tree that contains FileableCmisObject objects |
||
415 | * @see FileableCmisObject FileableCmisObject contained in returned TreeInterface |
||
416 | */ |
||
417 | View Code Duplication | public function getFolderTree($depth, OperationContextInterface $context = null) |
|
433 | |||
434 | /** |
||
435 | * Returns the path of the folder. |
||
436 | * |
||
437 | * @return string the absolute folder path |
||
438 | */ |
||
439 | public function getPath() |
||
476 | |||
477 | /** |
||
478 | * Returns if the folder is the root folder. |
||
479 | * |
||
480 | * @return boolean <code>true</code> if the folder is the root folder, <code>false</code> otherwise |
||
481 | */ |
||
482 | public function isRootFolder() |
||
486 | |||
487 | /** |
||
488 | * Returns the list of the allowed object types in this folder (CMIS property cmis:allowedChildObjectTypeIds). |
||
489 | * If the list is empty or <code>null</code> all object types are allowed. |
||
490 | * |
||
491 | * @return ObjectTypeInterface[] the property value or <code>null</code> if the property hasn't been requested, |
||
492 | * hasn't been provided by the repository, or the property value isn't set |
||
493 | */ |
||
494 | public function getAllowedChildObjectTypes() |
||
509 | |||
510 | /** |
||
511 | * Returns the parent id or <code>null</code> if the folder is the root folder (CMIS property cmis:parentId). |
||
512 | * |
||
513 | * @return string|null the property value or <code>null</code> if the property hasn't been requested, hasn't |
||
514 | * been provided by the repository, or the folder is the root folder |
||
515 | */ |
||
516 | public function getParentId() |
||
520 | |||
521 | |||
522 | /** |
||
523 | * Converts a binding container into an API container. |
||
524 | * |
||
525 | * @param ObjectInFolderContainerInterface[] $bindingContainerList |
||
526 | * @param OperationContextInterface $context |
||
527 | * @return TreeInterface[] |
||
528 | */ |
||
529 | private function convertBindingContainer(array $bindingContainerList, OperationContextInterface $context) |
||
534 | } |
||
535 |
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.