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 Document 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 Document, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
34 | class Document extends AbstractFileableCmisObject implements DocumentInterface |
||
35 | { |
||
36 | /** |
||
37 | * Appends a content stream to the content stream of the document and refreshes this object afterwards. |
||
38 | * If the repository created a new version, this new document is returned. |
||
39 | * Otherwise the current document is returned. |
||
40 | * The stream in contentStream is consumed but not closed by this method. |
||
41 | * |
||
42 | * @param StreamInterface $contentStream the content stream |
||
43 | * @param boolean $isLastChunk indicates if this stream is the last chunk of the content |
||
44 | * @param boolean $refresh if this parameter is set to <code>true</code>, this object will be refreshed after the |
||
45 | * content stream has been appended |
||
46 | * @return ObjectIdInterface|null the updated object ID, or <code>null</code> if the repository did not return |
||
47 | * an object ID |
||
48 | * @throws CmisNotSupportedException |
||
49 | */ |
||
50 | public function appendContentStream(StreamInterface $contentStream, $isLastChunk, $refresh = true) |
||
77 | |||
78 | /** |
||
79 | * If this is a PWC (private working copy) the check out will be reversed. |
||
80 | */ |
||
81 | public function cancelCheckOut() |
||
87 | |||
88 | /** |
||
89 | * If this is a PWC (private working copy) it performs a check in. |
||
90 | * If this is not a PWC an exception will be thrown. |
||
91 | * The stream in contentStream is consumed but not closed by this method. |
||
92 | * |
||
93 | * @param boolean $major <code>true</code> if the checked-in document object MUST be a major version. |
||
94 | * <code>false</code> if the checked-in document object MUST NOT be a major version but a minor version. |
||
95 | * @param array $properties The property values that MUST be applied to the checked-in document object. |
||
96 | * @param StreamInterface $contentStream The content stream that MUST be stored for the checked-in document object. |
||
97 | * The method of passing the contentStream to the server and the encoding mechanism will be specified by each |
||
98 | * specific binding. MUST be required if the type requires it. |
||
99 | * @param string $checkinComment Textual comment associated with the given version. MAY be "not set". |
||
100 | * @param PolicyInterface[] $policies A list of policy ids that MUST be applied to the newly-created document |
||
101 | * object |
||
102 | * @param AceInterface[] $addAces A list of ACEs that MUST be added to the newly-created document object. |
||
103 | * @param AceInterface[] $removeAces A list of ACEs that MUST be removed from the newly-created document object. |
||
104 | * @return ObjectIdInterface|null The id of the checked-in document. <code>null</code> if repository has not |
||
105 | * returned the new object id which could happen in case of a repository error |
||
106 | */ |
||
107 | public function checkIn( |
||
150 | |||
151 | /** |
||
152 | * Checks out the document and returns the object ID of the PWC (private working copy). |
||
153 | * |
||
154 | * @return ObjectIdInterface|null PWC object ID |
||
155 | */ |
||
156 | public function checkOut() |
||
168 | |||
169 | /** |
||
170 | * Creates a copy of this document, including content. |
||
171 | * |
||
172 | * @param ObjectIdInterface|null $targetFolderId the ID of the target folder, <code>null</code> to create an unfiled |
||
173 | * document |
||
174 | * @param array $properties The property values that MUST be applied to the object. This list of properties SHOULD |
||
175 | * only contain properties whose values differ from the source document. The array key is the property name |
||
176 | * the value is the property value. |
||
177 | * @param VersioningState|null $versioningState An enumeration specifying what the versioning state of the |
||
178 | * newly-created object MUST be. Valid values are: |
||
179 | * <code>none</code> |
||
180 | * (default, if the object-type is not versionable) The document MUST be created as a non-versionable |
||
181 | * document. |
||
182 | * <code>checkedout</code> |
||
183 | * The document MUST be created in the checked-out state. The checked-out document MAY be |
||
184 | * visible to other users. |
||
185 | * <code>major</code> |
||
186 | * (default, if the object-type is versionable) The document MUST be created as a major version. |
||
187 | * <code>minor</code> |
||
188 | * The document MUST be created as a minor version. |
||
189 | * @param PolicyInterface[] $policies A list of policy ids that MUST be applied to the newly-created document |
||
190 | * object. |
||
191 | * @param AceInterface[] $addAces A list of ACEs that MUST be added to the newly-created document object, either |
||
192 | * using the ACL from folderId if specified, or being applied if no folderId is specified. |
||
193 | * @param AceInterface[] $removeAces A list of ACEs that MUST be removed from the newly-created document object, |
||
194 | * either using the ACL from folderId if specified, or being ignored if no folderId is specified. |
||
195 | * @param OperationContextInterface|null $context |
||
196 | * @return DocumentInterface the new document object or <code>null</code> if the parameter <code>context</code> was |
||
197 | * set to <code>null</code> |
||
198 | * @throws CmisRuntimeException Exception is thrown if the created object is not a document |
||
199 | */ |
||
200 | public function copy( |
||
240 | |||
241 | /** |
||
242 | * Copies the document manually. The content is streamed from the repository and back. |
||
243 | * |
||
244 | * @param ObjectIdInterface|null $targetFolderId the ID of the target folder, <code>null</code> to create an unfiled |
||
245 | * document |
||
246 | * @param array $properties The property values that MUST be applied to the object. This list of properties SHOULD |
||
247 | * only contain properties whose values differ from the source document. The array key is the property name |
||
248 | * the value is the property value. |
||
249 | * @param VersioningState|null $versioningState An enumeration specifying what the versioning state of the |
||
250 | * newly-created object MUST be. Valid values are: |
||
251 | * <code>none</code> |
||
252 | * (default, if the object-type is not versionable) The document MUST be created as a non-versionable |
||
253 | * document. |
||
254 | * <code>checkedout</code> |
||
255 | * The document MUST be created in the checked-out state. The checked-out document MAY be |
||
256 | * visible to other users. |
||
257 | * <code>major</code> |
||
258 | * (default, if the object-type is versionable) The document MUST be created as a major version. |
||
259 | * <code>minor</code> |
||
260 | * The document MUST be created as a minor version. |
||
261 | * @param PolicyInterface[] $policies A list of policy ids that MUST be applied to the newly-created document |
||
262 | * object. |
||
263 | * @param AceInterface[] $addAces A list of ACEs that MUST be added to the newly-created document object, either |
||
264 | * using the ACL from folderId if specified, or being applied if no folderId is specified. |
||
265 | * @param AceInterface[] $removeAces A list of ACEs that MUST be removed from the newly-created document object, |
||
266 | * either using the ACL from folderId if specified, or being ignored if no folderId is specified. |
||
267 | * @return ObjectIdInterface The id of the newly-created document. |
||
268 | * @throws CmisRuntimeException |
||
269 | */ |
||
270 | protected function copyViaClient( |
||
316 | |||
317 | /** |
||
318 | * Deletes this document and all its versions. |
||
319 | */ |
||
320 | public function deleteAllVersions() |
||
324 | |||
325 | /** |
||
326 | * Removes the current content stream from the document and refreshes this object afterwards. |
||
327 | * |
||
328 | * @param boolean $refresh if this parameter is set to <code>true</code>, this object will be refreshed after the |
||
329 | * content stream has been deleted |
||
330 | * @return DocumentInterface|null the updated document, or <code>null</code> if the repository did not return |
||
331 | * an object ID |
||
332 | */ |
||
333 | View Code Duplication | public function deleteContentStream($refresh = true) |
|
357 | |||
358 | /** |
||
359 | * Fetches all versions of this document using the given OperationContext. |
||
360 | * The behavior of this method is undefined if the document is not versionable |
||
361 | * and can be different for each repository. |
||
362 | * |
||
363 | * @param OperationContextInterface|null $context |
||
364 | * @return DocumentInterface[] |
||
365 | */ |
||
366 | public function getAllVersions(OperationContextInterface $context = null) |
||
397 | |||
398 | /** |
||
399 | * Returns the content URL of the document or a rendition if the binding |
||
400 | * supports content URLs. |
||
401 | * |
||
402 | * Depending on the repository and the binding, the server might not return |
||
403 | * the content but an error message. Authentication data is not attached. |
||
404 | * That is, a user may have to re-authenticate to get the content. |
||
405 | * |
||
406 | * @param string|null $streamId the ID of the rendition or <code>null</code> for the document |
||
407 | * |
||
408 | * @return string|null the content URL of the document or rendition or <code>null</code> if |
||
409 | * the binding does not support content URLs |
||
410 | */ |
||
411 | public function getContentUrl($streamId = null) |
||
424 | |||
425 | /** |
||
426 | * Retrieves the content stream that is associated with the given stream ID. |
||
427 | * This is usually a rendition of the document. |
||
428 | * |
||
429 | * @param string|null $streamId the stream ID |
||
430 | * @param integer|null $offset the offset of the stream or <code>null</code> to read the stream from the beginning |
||
431 | * @param integer|null $length the maximum length of the stream or <code>null</code> to read to the end of the |
||
432 | * stream |
||
433 | * @return StreamInterface|null the content stream, or <code>null</code> if no content is associated with this |
||
434 | * stream ID |
||
435 | */ |
||
436 | public function getContentStream($streamId = null, $offset = null, $length = null) |
||
440 | |||
441 | /** |
||
442 | * Fetches the latest major or minor version of this document using the given OperationContext. |
||
443 | * |
||
444 | * @param boolean $major if <code>true</code> the latest major version will be returned, |
||
445 | * otherwise the very last version will be returned |
||
446 | * @param OperationContextInterface|null $context |
||
447 | * @return DocumentInterface the latest document object |
||
448 | */ |
||
449 | public function getObjectOfLatestVersion($major, OperationContextInterface $context = null) |
||
455 | |||
456 | /** |
||
457 | * Sets a new content stream for the document. If the repository created a new version, |
||
458 | * the object ID of this new version is returned. Otherwise the object ID of the current document is returned. |
||
459 | * The stream in contentStream is consumed but not closed by this method. |
||
460 | * |
||
461 | * @param StreamInterface $contentStream the content stream |
||
462 | * @param boolean $overwrite if this parameter is set to <code>false</code> and the document already has content, |
||
463 | * the repository throws a CmisContentAlreadyExistsException |
||
464 | * @param boolean $refresh if this parameter is set to <code>true</code>, this object will be refreshed |
||
465 | * after the new content has been set |
||
466 | * @return ObjectIdInterface|null the updated object ID, or <code>null</code> if the repository did not return |
||
467 | * an object ID |
||
468 | */ |
||
469 | View Code Duplication | public function setContentStream(StreamInterface $contentStream, $overwrite, $refresh = true) |
|
492 | |||
493 | /** |
||
494 | * Returns the checkin comment (CMIS property cmis:checkinComment). |
||
495 | * |
||
496 | * @return string|null the checkin comment of this version or <code>null</code> if the property hasn't |
||
497 | * been requested, hasn't been provided by the repository, or the property value isn't set |
||
498 | */ |
||
499 | public function getCheckinComment() |
||
503 | |||
504 | /** |
||
505 | * Returns the content stream filename or <code>null</code> if the document has no content |
||
506 | * (CMIS property cmis:contentStreamFileName). |
||
507 | * |
||
508 | * @return string|null the content stream filename of this document or <code>null</code> if the property hasn't |
||
509 | * been requested, hasn't been provided by the repository, or the document has no content |
||
510 | */ |
||
511 | public function getContentStreamFileName() |
||
515 | |||
516 | /** |
||
517 | * Returns the content hashes or <code>null</code> if the document has no content |
||
518 | * (CMIS property cmis:contentStreamHash). |
||
519 | * |
||
520 | * @return ContentStreamHashInterface[]|null the list of content hashes or <code>null</code> if the property |
||
521 | * hasn't been requested, hasn't been provided by the repository, or the document has no content |
||
522 | */ |
||
523 | public function getContentStreamHashes() |
||
529 | |||
530 | /** |
||
531 | * Returns the content stream ID or <code>null</code> if the document has no content |
||
532 | * (CMIS property cmis:contentStreamId). |
||
533 | * |
||
534 | * @return string|null the content stream ID of this document or <code>null</code> if the property hasn't |
||
535 | * been requested, hasn't been provided by the repository, or the document has no content |
||
536 | */ |
||
537 | public function getContentStreamId() |
||
541 | |||
542 | /** |
||
543 | * Returns the content stream length or <code>null</code> if the document has no content (CMIS property |
||
544 | * cmis:contentStreamLength). |
||
545 | * |
||
546 | * @return integer the content stream length of this document or <code>null</code> if the property hasn't been |
||
547 | * requested, hasn't been provided by the repository, or the document has no content |
||
548 | */ |
||
549 | public function getContentStreamLength() |
||
553 | |||
554 | /** |
||
555 | * Returns the content stream MIME type or <code>null</code> if the document has no content |
||
556 | * (CMIS property cmis:contentStreamMimeType). |
||
557 | * |
||
558 | * @return string|null the content stream MIME type of this document or <code>null</code> if the property hasn't |
||
559 | * been requested, hasn't been provided by the repository, or the document has no content |
||
560 | */ |
||
561 | public function getContentStreamMimeType() |
||
565 | |||
566 | /** |
||
567 | * Returns the version label (CMIS property cmis:versionLabel). |
||
568 | * |
||
569 | * @return string|null the version label of the document or <code>null</code> if the property hasn't been requested, |
||
570 | * hasn't been provided by the repository, or the property value isn't set |
||
571 | */ |
||
572 | public function getVersionLabel() |
||
576 | |||
577 | /** |
||
578 | * Returns the user who checked out this version series (CMIS property cmis:versionSeriesCheckedOutBy). |
||
579 | * |
||
580 | * @return string|null the user who checked out this version series or <code>null</code> if the property hasn't |
||
581 | * been requested, hasn't been provided by the repository, or the property value isn't set |
||
582 | */ |
||
583 | public function getVersionSeriesCheckedOutBy() |
||
587 | |||
588 | /** |
||
589 | * Returns the PWC ID of this version series (CMIS property cmis:versionSeriesCheckedOutId). |
||
590 | * Some repositories provided this value only to the user who checked out the version series. |
||
591 | * |
||
592 | * @return string|null the PWC ID of this version series or <code>null</code> if the property hasn't been requested, |
||
593 | * hasn't been provided by the repository, or the property value isn't set |
||
594 | */ |
||
595 | public function getVersionSeriesCheckedOutId() |
||
599 | |||
600 | /** |
||
601 | * Returns the version series ID (CMIS property cmis:versionSeriesId). |
||
602 | * |
||
603 | * @return string|null the version series ID of the document or <code>null</code> if the property hasn't |
||
604 | * been requested, hasn't been provided by the repository, or the property value isn't set |
||
605 | */ |
||
606 | public function getVersionSeriesId() |
||
610 | |||
611 | /** |
||
612 | * Returns <code>true</code> if this document is immutable (CMIS property cmis:isImmutable). |
||
613 | * |
||
614 | * @return boolean|null the immutable flag of the document or <code>null</code> if the property hasn't |
||
615 | * been requested, hasn't been provided by the repository, or the property value isn't set |
||
616 | */ |
||
617 | public function isImmutable() |
||
621 | |||
622 | /** |
||
623 | * Returns <code>true</code> if this document is the latest version (CMIS property cmis:isLatestVersion). |
||
624 | * |
||
625 | * @return boolean|null the latest version flag of the document or <code>null</code> if the property hasn't |
||
626 | * been requested, hasn't been provided by the repository, or the property value isn't set |
||
627 | */ |
||
628 | public function isLatestMajorVersion() |
||
632 | |||
633 | /** |
||
634 | * Returns <code>true</code> if this document is the latest version (CMIS property cmis:isLatestVersion). |
||
635 | * |
||
636 | * @return boolean|null the latest version flag of the document or <code>null</code> if the property hasn't |
||
637 | * been requested, hasn't been provided by the repository, or the property value isn't set |
||
638 | */ |
||
639 | public function isLatestVersion() |
||
643 | |||
644 | /** |
||
645 | * Returns <code>true</code> if this document is a major version (CMIS property cmis:isMajorVersion). |
||
646 | * |
||
647 | * @return boolean|null the major version flag of the document or <code>null</code> if the property hasn't |
||
648 | * been requested, hasn't been provided by the repository, or the property value isn't set |
||
649 | */ |
||
650 | public function isMajorVersion() |
||
654 | |||
655 | /** |
||
656 | * Returns <code>true</code> if this document is the PWC (CMIS property cmis:isPrivateWorkingCopy). |
||
657 | * |
||
658 | * @return boolean|null the PWC flag of the document or <code>null</code> if the property hasn't been requested, |
||
659 | * hasn't been provided by the repository, or the property value isn't set |
||
660 | */ |
||
661 | public function isPrivateWorkingCopy() |
||
665 | |||
666 | /** |
||
667 | * Returns <code>true</code> if this version series is checked out (CMIS property cmis:isVersionSeriesCheckedOut). |
||
668 | * |
||
669 | * @return boolean|null the version series checked out flag of the document or <code>null</code> if the property |
||
670 | * hasn't been requested, hasn't been provided by the repository, or the property value isn't set |
||
671 | */ |
||
672 | public function isVersionSeriesCheckedOut() |
||
676 | } |
||
677 |