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 |
||
33 | class Document extends AbstractFileableCmisObject implements DocumentInterface |
||
34 | { |
||
35 | /** |
||
36 | * Appends a content stream to the content stream of the document and refreshes this object afterwards. |
||
37 | * If the repository created a new version, this new document is returned. |
||
38 | * Otherwise the current document is returned. |
||
39 | * The stream in contentStream is consumed but not closed by this method. |
||
40 | * |
||
41 | * @param StreamInterface $contentStream the content stream |
||
42 | * @param boolean $isLastChunk indicates if this stream is the last chunk of the content |
||
43 | * @param boolean $refresh if this parameter is set to <code>true</code>, this object will be refreshed after the |
||
44 | * content stream has been appended |
||
45 | * @return ObjectIdInterface|null the updated object ID, or <code>null</code> if the repository did not return |
||
46 | * an object ID |
||
47 | * @throws CmisNotSupportedException |
||
48 | */ |
||
49 | public function appendContentStream(StreamInterface $contentStream, $isLastChunk, $refresh = true) |
||
76 | |||
77 | /** |
||
78 | * If this is a PWC (private working copy) the check out will be reversed. |
||
79 | */ |
||
80 | public function cancelCheckOut() |
||
86 | |||
87 | /** |
||
88 | * If this is a PWC (private working copy) it performs a check in. |
||
89 | * If this is not a PWC an exception will be thrown. |
||
90 | * The stream in contentStream is consumed but not closed by this method. |
||
91 | * |
||
92 | * @param boolean $major <code>true</code> if the checked-in document object MUST be a major version. |
||
93 | * <code>false</code> if the checked-in document object MUST NOT be a major version but a minor version. |
||
94 | * @param array $properties The property values that MUST be applied to the checked-in document object. |
||
95 | * @param StreamInterface $contentStream The content stream that MUST be stored for the checked-in document object. |
||
96 | * The method of passing the contentStream to the server and the encoding mechanism will be specified by each |
||
97 | * specific binding. MUST be required if the type requires it. |
||
98 | * @param string $checkinComment Textual comment associated with the given version. MAY be "not set". |
||
99 | * @param PolicyInterface[] $policies A list of policy ids that MUST be applied to the newly-created document |
||
100 | * object |
||
101 | * @param AceInterface[] $addAces A list of ACEs that MUST be added to the newly-created document object. |
||
102 | * @param AceInterface[] $removeAces A list of ACEs that MUST be removed from the newly-created document object. |
||
103 | * @return ObjectIdInterface|null The id of the checked-in document. <code>null</code> if repository has not |
||
104 | * returned the new object id which could happen in case of a repository error |
||
105 | */ |
||
106 | public function checkIn( |
||
149 | |||
150 | /** |
||
151 | * Checks out the document and returns the object ID of the PWC (private working copy). |
||
152 | * |
||
153 | * @return ObjectIdInterface|null PWC object ID |
||
154 | */ |
||
155 | public function checkOut() |
||
167 | |||
168 | /** |
||
169 | * Creates a copy of this document, including content. |
||
170 | * |
||
171 | * @param ObjectIdInterface|null $targetFolderId the ID of the target folder, <code>null</code> to create an unfiled |
||
172 | * document |
||
173 | * @param array $properties The property values that MUST be applied to the object. This list of properties SHOULD |
||
174 | * only contain properties whose values differ from the source document. The array key is the property name |
||
175 | * the value is the property value. |
||
176 | * @param VersioningState|null $versioningState An enumeration specifying what the versioning state of the |
||
177 | * newly-created object MUST be. Valid values are: |
||
178 | * <code>none</code> |
||
179 | * (default, if the object-type is not versionable) The document MUST be created as a non-versionable |
||
180 | * document. |
||
181 | * <code>checkedout</code> |
||
182 | * The document MUST be created in the checked-out state. The checked-out document MAY be |
||
183 | * visible to other users. |
||
184 | * <code>major</code> |
||
185 | * (default, if the object-type is versionable) The document MUST be created as a major version. |
||
186 | * <code>minor</code> |
||
187 | * The document MUST be created as a minor version. |
||
188 | * @param PolicyInterface[] $policies A list of policy ids that MUST be applied to the newly-created document |
||
189 | * object. |
||
190 | * @param AceInterface[] $addAces A list of ACEs that MUST be added to the newly-created document object, either |
||
191 | * using the ACL from folderId if specified, or being applied if no folderId is specified. |
||
192 | * @param AceInterface[] $removeAces A list of ACEs that MUST be removed from the newly-created document object, |
||
193 | * either using the ACL from folderId if specified, or being ignored if no folderId is specified. |
||
194 | * @param OperationContextInterface|null $context |
||
195 | * @return DocumentInterface the new document object or <code>null</code> if the parameter <code>context</code> was |
||
196 | * set to <code>null</code> |
||
197 | * @throws CmisRuntimeException Exception is thrown if the created object is not a document |
||
198 | */ |
||
199 | public function copy( |
||
239 | |||
240 | /** |
||
241 | * Copies the document manually. The content is streamed from the repository and back. |
||
242 | * |
||
243 | * @param ObjectIdInterface|null $targetFolderId the ID of the target folder, <code>null</code> to create an unfiled |
||
244 | * document |
||
245 | * @param array $properties The property values that MUST be applied to the object. This list of properties SHOULD |
||
246 | * only contain properties whose values differ from the source document. The array key is the property name |
||
247 | * the value is the property value. |
||
248 | * @param VersioningState|null $versioningState An enumeration specifying what the versioning state of the |
||
249 | * newly-created object MUST be. Valid values are: |
||
250 | * <code>none</code> |
||
251 | * (default, if the object-type is not versionable) The document MUST be created as a non-versionable |
||
252 | * document. |
||
253 | * <code>checkedout</code> |
||
254 | * The document MUST be created in the checked-out state. The checked-out document MAY be |
||
255 | * visible to other users. |
||
256 | * <code>major</code> |
||
257 | * (default, if the object-type is versionable) The document MUST be created as a major version. |
||
258 | * <code>minor</code> |
||
259 | * The document MUST be created as a minor version. |
||
260 | * @param PolicyInterface[] $policies A list of policy ids that MUST be applied to the newly-created document |
||
261 | * object. |
||
262 | * @param AceInterface[] $addAces A list of ACEs that MUST be added to the newly-created document object, either |
||
263 | * using the ACL from folderId if specified, or being applied if no folderId is specified. |
||
264 | * @param AceInterface[] $removeAces A list of ACEs that MUST be removed from the newly-created document object, |
||
265 | * either using the ACL from folderId if specified, or being ignored if no folderId is specified. |
||
266 | * @return ObjectIdInterface The id of the newly-created document. |
||
267 | * @throws CmisRuntimeException |
||
268 | */ |
||
269 | protected function copyViaClient( |
||
315 | |||
316 | /** |
||
317 | * Deletes this document and all its versions. |
||
318 | */ |
||
319 | public function deleteAllVersions() |
||
323 | |||
324 | /** |
||
325 | * Removes the current content stream from the document and refreshes this object afterwards. |
||
326 | * |
||
327 | * @param boolean $refresh if this parameter is set to <code>true</code>, this object will be refreshed after the |
||
328 | * content stream has been deleted |
||
329 | * @return DocumentInterface|null the updated document, or <code>null</code> if the repository did not return |
||
330 | * an object ID |
||
331 | */ |
||
332 | View Code Duplication | public function deleteContentStream($refresh = true) |
|
356 | |||
357 | /** |
||
358 | * Fetches all versions of this document using the given OperationContext. |
||
359 | * The behavior of this method is undefined if the document is not versionable |
||
360 | * and can be different for each repository. |
||
361 | * |
||
362 | * @param OperationContextInterface|null $context |
||
363 | * @return DocumentInterface[] |
||
364 | */ |
||
365 | public function getAllVersions(OperationContextInterface $context = null) |
||
391 | |||
392 | /** |
||
393 | * Returns the content URL of the document or a rendition if the binding |
||
394 | * supports content URLs. |
||
395 | * |
||
396 | * Depending on the repository and the binding, the server might not return |
||
397 | * the content but an error message. Authentication data is not attached. |
||
398 | * That is, a user may have to re-authenticate to get the content. |
||
399 | * |
||
400 | * @param string|null $streamId the ID of the rendition or <code>null</code> for the document |
||
401 | * |
||
402 | * @return string|null the content URL of the document or rendition or <code>null</code> if |
||
403 | * the binding does not support content URLs |
||
404 | */ |
||
405 | public function getContentUrl($streamId = null) |
||
418 | |||
419 | /** |
||
420 | * Retrieves the content stream that is associated with the given stream ID. |
||
421 | * This is usually a rendition of the document. |
||
422 | * |
||
423 | * @param string|null $streamId the stream ID |
||
424 | * @param integer|null $offset the offset of the stream or <code>null</code> to read the stream from the beginning |
||
425 | * @param integer|null $length the maximum length of the stream or <code>null</code> to read to the end of the |
||
426 | * stream |
||
427 | * @return StreamInterface|null the content stream, or <code>null</code> if no content is associated with this |
||
428 | * stream ID |
||
429 | */ |
||
430 | public function getContentStream($streamId = null, $offset = null, $length = null) |
||
434 | |||
435 | /** |
||
436 | * Fetches the latest major or minor version of this document using the given OperationContext. |
||
437 | * |
||
438 | * @param boolean $major if <code>true</code> the latest major version will be returned, |
||
439 | * otherwise the very last version will be returned |
||
440 | * @param OperationContextInterface|null $context |
||
441 | * @return DocumentInterface the latest document object |
||
442 | */ |
||
443 | public function getObjectOfLatestVersion($major, OperationContextInterface $context = null) |
||
449 | |||
450 | /** |
||
451 | * Sets a new content stream for the document. If the repository created a new version, |
||
452 | * the object ID of this new version is returned. Otherwise the object ID of the current document is returned. |
||
453 | * The stream in contentStream is consumed but not closed by this method. |
||
454 | * |
||
455 | * @param StreamInterface $contentStream the content stream |
||
456 | * @param boolean $overwrite if this parameter is set to <code>false</code> and the document already has content, |
||
457 | * the repository throws a CmisContentAlreadyExistsException |
||
458 | * @param boolean $refresh if this parameter is set to <code>true</code>, this object will be refreshed |
||
459 | * after the new content has been set |
||
460 | * @return ObjectIdInterface|null the updated object ID, or <code>null</code> if the repository did not return |
||
461 | * an object ID |
||
462 | */ |
||
463 | View Code Duplication | public function setContentStream(StreamInterface $contentStream, $overwrite, $refresh = true) |
|
486 | |||
487 | /** |
||
488 | * Returns the checkin comment (CMIS property cmis:checkinComment). |
||
489 | * |
||
490 | * @return string|null the checkin comment of this version or <code>null</code> if the property hasn't |
||
491 | * been requested, hasn't been provided by the repository, or the property value isn't set |
||
492 | */ |
||
493 | public function getCheckinComment() |
||
497 | |||
498 | /** |
||
499 | * Returns the content stream filename or <code>null</code> if the document has no content |
||
500 | * (CMIS property cmis:contentStreamFileName). |
||
501 | * |
||
502 | * @return string|null the content stream filename of this document or <code>null</code> if the property hasn't |
||
503 | * been requested, hasn't been provided by the repository, or the document has no content |
||
504 | */ |
||
505 | public function getContentStreamFileName() |
||
509 | |||
510 | /** |
||
511 | * Returns the content hashes or <code>null</code> if the document has no content |
||
512 | * (CMIS property cmis:contentStreamHash). |
||
513 | * |
||
514 | * @return ContentStreamHashInterface[]|null the list of content hashes or <code>null</code> if the property |
||
515 | * hasn't been requested, hasn't been provided by the repository, or the document has no content |
||
516 | */ |
||
517 | public function getContentStreamHashes() |
||
523 | |||
524 | /** |
||
525 | * Returns the content stream ID or <code>null</code> if the document has no content |
||
526 | * (CMIS property cmis:contentStreamId). |
||
527 | * |
||
528 | * @return string|null the content stream ID of this document or <code>null</code> if the property hasn't |
||
529 | * been requested, hasn't been provided by the repository, or the document has no content |
||
530 | */ |
||
531 | public function getContentStreamId() |
||
535 | |||
536 | /** |
||
537 | * Returns the content stream length or <code>null</code> if the document has no content (CMIS property |
||
538 | * cmis:contentStreamLength). |
||
539 | * |
||
540 | * @return integer the content stream length of this document or <code>null</code> if the property hasn't been |
||
541 | * requested, hasn't been provided by the repository, or the document has no content |
||
542 | */ |
||
543 | public function getContentStreamLength() |
||
547 | |||
548 | /** |
||
549 | * Returns the content stream MIME type or <code>null</code> if the document has no content |
||
550 | * (CMIS property cmis:contentStreamMimeType). |
||
551 | * |
||
552 | * @return string|null the content stream MIME type of this document or <code>null</code> if the property hasn't |
||
553 | * been requested, hasn't been provided by the repository, or the document has no content |
||
554 | */ |
||
555 | public function getContentStreamMimeType() |
||
559 | |||
560 | /** |
||
561 | * Returns the version label (CMIS property cmis:versionLabel). |
||
562 | * |
||
563 | * @return string|null the version label of the document or <code>null</code> if the property hasn't been requested, |
||
564 | * hasn't been provided by the repository, or the property value isn't set |
||
565 | */ |
||
566 | public function getVersionLabel() |
||
570 | |||
571 | /** |
||
572 | * Returns the user who checked out this version series (CMIS property cmis:versionSeriesCheckedOutBy). |
||
573 | * |
||
574 | * @return string|null the user who checked out this version series or <code>null</code> if the property hasn't |
||
575 | * been requested, hasn't been provided by the repository, or the property value isn't set |
||
576 | */ |
||
577 | public function getVersionSeriesCheckedOutBy() |
||
581 | |||
582 | /** |
||
583 | * Returns the PWC ID of this version series (CMIS property cmis:versionSeriesCheckedOutId). |
||
584 | * Some repositories provided this value only to the user who checked out the version series. |
||
585 | * |
||
586 | * @return string|null the PWC ID of this version series or <code>null</code> if the property hasn't been requested, |
||
587 | * hasn't been provided by the repository, or the property value isn't set |
||
588 | */ |
||
589 | public function getVersionSeriesCheckedOutId() |
||
593 | |||
594 | /** |
||
595 | * Returns the version series ID (CMIS property cmis:versionSeriesId). |
||
596 | * |
||
597 | * @return string|null the version series ID of the document or <code>null</code> if the property hasn't |
||
598 | * been requested, hasn't been provided by the repository, or the property value isn't set |
||
599 | */ |
||
600 | public function getVersionSeriesId() |
||
604 | |||
605 | /** |
||
606 | * Returns <code>true</code> if this document is immutable (CMIS property cmis:isImmutable). |
||
607 | * |
||
608 | * @return boolean|null the immutable flag of the document or <code>null</code> if the property hasn't |
||
609 | * been requested, hasn't been provided by the repository, or the property value isn't set |
||
610 | */ |
||
611 | public function isImmutable() |
||
615 | |||
616 | /** |
||
617 | * Returns <code>true</code> if this document is the latest version (CMIS property cmis:isLatestVersion). |
||
618 | * |
||
619 | * @return boolean|null the latest version flag of the document or <code>null</code> if the property hasn't |
||
620 | * been requested, hasn't been provided by the repository, or the property value isn't set |
||
621 | */ |
||
622 | public function isLatestMajorVersion() |
||
626 | |||
627 | /** |
||
628 | * Returns <code>true</code> if this document is the latest version (CMIS property cmis:isLatestVersion). |
||
629 | * |
||
630 | * @return boolean|null the latest version flag of the document or <code>null</code> if the property hasn't |
||
631 | * been requested, hasn't been provided by the repository, or the property value isn't set |
||
632 | */ |
||
633 | public function isLatestVersion() |
||
637 | |||
638 | /** |
||
639 | * Returns <code>true</code> if this document is a major version (CMIS property cmis:isMajorVersion). |
||
640 | * |
||
641 | * @return boolean|null the major version flag of the document or <code>null</code> if the property hasn't |
||
642 | * been requested, hasn't been provided by the repository, or the property value isn't set |
||
643 | */ |
||
644 | public function isMajorVersion() |
||
648 | |||
649 | /** |
||
650 | * Returns <code>true</code> if this document is the PWC (CMIS property cmis:isPrivateWorkingCopy). |
||
651 | * |
||
652 | * @return boolean|null the PWC flag of the document or <code>null</code> if the property hasn't been requested, |
||
653 | * hasn't been provided by the repository, or the property value isn't set |
||
654 | */ |
||
655 | public function isPrivateWorkingCopy() |
||
659 | |||
660 | /** |
||
661 | * Returns <code>true</code> if this version series is checked out (CMIS property cmis:isVersionSeriesCheckedOut). |
||
662 | * |
||
663 | * @return boolean|null the version series checked out flag of the document or <code>null</code> if the property |
||
664 | * hasn't been requested, hasn't been provided by the repository, or the property value isn't set |
||
665 | */ |
||
666 | public function isVersionSeriesCheckedOut() |
||
670 | } |
||
671 |