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 Event 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 Event, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
30 | class Event extends Component |
||
31 | { |
||
32 | const TIME_TRANSPARENCY_OPAQUE = 'OPAQUE'; |
||
33 | const TIME_TRANSPARENCY_TRANSPARENT = 'TRANSPARENT'; |
||
34 | |||
35 | const STATUS_TENTATIVE = 'TENTATIVE'; |
||
36 | const STATUS_CONFIRMED = 'CONFIRMED'; |
||
37 | const STATUS_CANCELLED = 'CANCELLED'; |
||
38 | |||
39 | /** |
||
40 | * @var string |
||
41 | */ |
||
42 | protected $uniqueId; |
||
43 | |||
44 | /** |
||
45 | * The property indicates the date/time that the instance of |
||
46 | * the iCalendar object was created. |
||
47 | * |
||
48 | * The value MUST be specified in the UTC time format. |
||
49 | * |
||
50 | * @var \DateTime |
||
51 | */ |
||
52 | protected $dtStamp; |
||
53 | |||
54 | /** |
||
55 | * @var \DateTime |
||
56 | */ |
||
57 | protected $dtStart; |
||
58 | |||
59 | /** |
||
60 | * Preferentially chosen over the duration if both are set. |
||
61 | * |
||
62 | * @var \DateTime |
||
63 | */ |
||
64 | protected $dtEnd; |
||
65 | |||
66 | /** |
||
67 | * @var \DateInterval |
||
68 | */ |
||
69 | protected $duration; |
||
70 | |||
71 | /** |
||
72 | * @var bool |
||
73 | */ |
||
74 | protected $noTime = false; |
||
75 | |||
76 | /** |
||
77 | * @var string |
||
78 | */ |
||
79 | protected $url; |
||
80 | |||
81 | /** |
||
82 | * @var string |
||
83 | */ |
||
84 | protected $location; |
||
85 | |||
86 | /** |
||
87 | * @var string |
||
88 | */ |
||
89 | protected $locationTitle; |
||
90 | |||
91 | /** |
||
92 | * @var Geo |
||
93 | */ |
||
94 | protected $locationGeo; |
||
95 | |||
96 | /** |
||
97 | * @var string |
||
98 | */ |
||
99 | protected $summary; |
||
100 | |||
101 | /** |
||
102 | * @var Organizer |
||
103 | */ |
||
104 | protected $organizer; |
||
105 | |||
106 | /** |
||
107 | * @see https://tools.ietf.org/html/rfc5545#section-3.8.2.7 |
||
108 | * |
||
109 | * @var string |
||
110 | */ |
||
111 | protected $transparency = self::TIME_TRANSPARENCY_OPAQUE; |
||
112 | |||
113 | /** |
||
114 | * If set to true the timezone will be added to the event. |
||
115 | * |
||
116 | * @var bool |
||
117 | */ |
||
118 | protected $useTimezone = false; |
||
119 | |||
120 | /** |
||
121 | * If set will be used as the timezone identifier. |
||
122 | * |
||
123 | * @var string |
||
124 | */ |
||
125 | protected $timezoneString = ''; |
||
126 | |||
127 | /** |
||
128 | * @var int |
||
129 | */ |
||
130 | protected $sequence = 0; |
||
131 | |||
132 | /** |
||
133 | * @var Attendees |
||
134 | */ |
||
135 | protected $attendees; |
||
136 | |||
137 | /** |
||
138 | * @var string |
||
139 | */ |
||
140 | protected $description; |
||
141 | |||
142 | /** |
||
143 | * @var string |
||
144 | */ |
||
145 | protected $descriptionHTML; |
||
146 | |||
147 | /** |
||
148 | * @var string |
||
149 | */ |
||
150 | protected $status; |
||
151 | |||
152 | /** |
||
153 | * @var RecurrenceRule |
||
154 | */ |
||
155 | protected $recurrenceRule; |
||
156 | |||
157 | /** |
||
158 | * @var array |
||
159 | */ |
||
160 | protected $recurrenceRules = []; |
||
161 | |||
162 | /** |
||
163 | * This property specifies the date and time that the calendar |
||
164 | * information was created. |
||
165 | * |
||
166 | * The value MUST be specified in the UTC time format. |
||
167 | * |
||
168 | * @var \DateTime |
||
169 | */ |
||
170 | protected $created; |
||
171 | |||
172 | /** |
||
173 | * The property specifies the date and time that the information |
||
174 | * associated with the calendar component was last revised. |
||
175 | * |
||
176 | * The value MUST be specified in the UTC time format. |
||
177 | * |
||
178 | * @var \DateTime |
||
179 | */ |
||
180 | protected $modified; |
||
181 | |||
182 | /** |
||
183 | * Indicates if the UTC time should be used or not. |
||
184 | * |
||
185 | * @var bool |
||
186 | */ |
||
187 | protected $useUtc = true; |
||
188 | |||
189 | /** |
||
190 | * @var bool |
||
191 | */ |
||
192 | protected $cancelled; |
||
193 | |||
194 | /** |
||
195 | * This property is used to specify categories or subtypes |
||
196 | * of the calendar component. The categories are useful in searching |
||
197 | * for a calendar component of a particular type and category. |
||
198 | * |
||
199 | * @see https://tools.ietf.org/html/rfc5545#section-3.8.1.2 |
||
200 | * |
||
201 | * @var array |
||
202 | */ |
||
203 | protected $categories; |
||
204 | |||
205 | /** |
||
206 | * https://tools.ietf.org/html/rfc5545#section-3.8.1.3. |
||
207 | * |
||
208 | * @var bool |
||
209 | */ |
||
210 | protected $isPrivate = false; |
||
211 | |||
212 | /** |
||
213 | * Dates to be excluded from a series of events. |
||
214 | * |
||
215 | * @var \DateTimeInterface[] |
||
216 | */ |
||
217 | protected $exDates = []; |
||
218 | |||
219 | /** |
||
220 | * @var RecurrenceId |
||
221 | */ |
||
222 | protected $recurrenceId; |
||
223 | |||
224 | /** |
||
225 | * @var Attachment[] |
||
226 | */ |
||
227 | protected $attachments = []; |
||
228 | |||
229 | 26 | public function __construct(string $uniqueId = null) |
|
238 | |||
239 | /** |
||
240 | * {@inheritdoc} |
||
241 | */ |
||
242 | 7 | public function getType() |
|
246 | |||
247 | /** |
||
248 | * {@inheritdoc} |
||
249 | */ |
||
250 | 17 | public function buildPropertyBag() |
|
381 | |||
382 | /** |
||
383 | * @param $dtEnd |
||
384 | * |
||
385 | * @return $this |
||
386 | */ |
||
387 | 5 | public function setDtEnd($dtEnd) |
|
393 | |||
394 | 2 | public function getDtEnd() |
|
398 | |||
399 | 5 | public function setDtStart($dtStart) |
|
405 | |||
406 | 2 | public function getDtStart() |
|
410 | |||
411 | /** |
||
412 | * @param $dtStamp |
||
413 | * |
||
414 | * @return $this |
||
415 | */ |
||
416 | 1 | public function setDtStamp($dtStamp) |
|
422 | |||
423 | /** |
||
424 | * @param $duration |
||
425 | * |
||
426 | * @return $this |
||
427 | */ |
||
428 | 1 | public function setDuration($duration) |
|
434 | |||
435 | /** |
||
436 | * @param string $location |
||
437 | * @param string $title |
||
438 | * @param Geo|string $geo |
||
439 | * |
||
440 | * @return $this |
||
441 | */ |
||
442 | 3 | public function setLocation($location, $title = '', $geo = null) |
|
460 | |||
461 | /** |
||
462 | * @param Geo $geoProperty |
||
463 | * |
||
464 | * @return $this |
||
465 | */ |
||
466 | 1 | public function setGeoLocation(Geo $geoProperty) |
|
472 | |||
473 | /** |
||
474 | * @param $noTime |
||
475 | * |
||
476 | * @return $this |
||
477 | */ |
||
478 | 1 | public function setNoTime($noTime) |
|
484 | |||
485 | /** |
||
486 | * @param int $sequence |
||
487 | * |
||
488 | * @return $this |
||
489 | */ |
||
490 | 2 | public function setSequence($sequence) |
|
496 | |||
497 | /** |
||
498 | * @return int |
||
499 | */ |
||
500 | 1 | public function getSequence() |
|
504 | |||
505 | /** |
||
506 | * @param Organizer $organizer |
||
507 | * |
||
508 | * @return $this |
||
509 | */ |
||
510 | 2 | public function setOrganizer(Organizer $organizer) |
|
516 | |||
517 | /** |
||
518 | * @param $summary |
||
519 | * |
||
520 | * @return $this |
||
521 | */ |
||
522 | 1 | public function setSummary($summary) |
|
528 | |||
529 | /** |
||
530 | * @param $uniqueId |
||
531 | * |
||
532 | * @return $this |
||
533 | */ |
||
534 | 1 | public function setUniqueId($uniqueId) |
|
540 | |||
541 | /** |
||
542 | * @return string |
||
543 | */ |
||
544 | 2 | public function getUniqueId() |
|
548 | |||
549 | /** |
||
550 | * @param $url |
||
551 | * |
||
552 | * @return $this |
||
553 | */ |
||
554 | 1 | public function setUrl($url) |
|
560 | |||
561 | /** |
||
562 | * @param $useTimezone |
||
563 | * |
||
564 | * @return $this |
||
565 | */ |
||
566 | public function setUseTimezone($useTimezone) |
||
572 | |||
573 | /** |
||
574 | * @return bool |
||
575 | */ |
||
576 | public function getUseTimezone() |
||
580 | |||
581 | /** |
||
582 | * @param $timezoneString |
||
583 | * |
||
584 | * @return $this |
||
585 | */ |
||
586 | 2 | public function setTimezoneString($timezoneString) |
|
592 | |||
593 | /** |
||
594 | * @return bool |
||
595 | */ |
||
596 | 1 | public function getTimezoneString() |
|
600 | |||
601 | /** |
||
602 | * @param Attendees $attendees |
||
603 | * |
||
604 | * @return $this |
||
605 | */ |
||
606 | public function setAttendees(Attendees $attendees) |
||
612 | |||
613 | /** |
||
614 | * @param string $attendee |
||
615 | * @param array $params |
||
616 | * |
||
617 | * @return $this |
||
618 | */ |
||
619 | public function addAttendee($attendee, $params = []) |
||
625 | |||
626 | /** |
||
627 | * @return Attendees |
||
628 | */ |
||
629 | public function getAttendees(): Attendees |
||
633 | |||
634 | /** |
||
635 | * @param $description |
||
636 | * |
||
637 | * @return $this |
||
638 | */ |
||
639 | 4 | public function setDescription($description) |
|
645 | |||
646 | /** |
||
647 | * @param $descriptionHTML |
||
648 | * |
||
649 | * @return $this |
||
650 | */ |
||
651 | public function setDescriptionHTML($descriptionHTML) |
||
657 | |||
658 | /** |
||
659 | * @param bool $useUtc |
||
660 | * |
||
661 | * @return $this |
||
662 | */ |
||
663 | public function setUseUtc($useUtc = true) |
||
669 | |||
670 | /** |
||
671 | * @return string |
||
672 | */ |
||
673 | public function getDescription() |
||
677 | |||
678 | /** |
||
679 | * @return string |
||
680 | */ |
||
681 | public function getDescriptionHTML() |
||
685 | |||
686 | /** |
||
687 | * @param $status |
||
688 | * |
||
689 | * @return $this |
||
690 | */ |
||
691 | public function setCancelled($status) |
||
697 | |||
698 | /** |
||
699 | * @param $transparency |
||
700 | * |
||
701 | * @return $this |
||
702 | * |
||
703 | * @throws \InvalidArgumentException |
||
704 | */ |
||
705 | View Code Duplication | public function setTimeTransparency($transparency) |
|
718 | |||
719 | /** |
||
720 | * @param $status |
||
721 | * |
||
722 | * @return $this |
||
723 | * |
||
724 | * @throws \InvalidArgumentException |
||
725 | */ |
||
726 | public function setStatus($status) |
||
740 | |||
741 | /** |
||
742 | * @deprecated Deprecated since version 0.11.0, to be removed in 1.0. Use addRecurrenceRule instead. |
||
743 | * |
||
744 | * @param RecurrenceRule $recurrenceRule |
||
745 | * |
||
746 | * @return $this |
||
747 | */ |
||
748 | public function setRecurrenceRule(RecurrenceRule $recurrenceRule) |
||
756 | |||
757 | /** |
||
758 | * @deprecated Deprecated since version 0.11.0, to be removed in 1.0. Use getRecurrenceRules instead. |
||
759 | * |
||
760 | * @return RecurrenceRule |
||
761 | */ |
||
762 | public function getRecurrenceRule() |
||
768 | |||
769 | /** |
||
770 | * @param RecurrenceRule $recurrenceRule |
||
771 | * |
||
772 | * @return $this |
||
773 | */ |
||
774 | public function addRecurrenceRule(RecurrenceRule $recurrenceRule) |
||
780 | |||
781 | /** |
||
782 | * @return array |
||
783 | */ |
||
784 | public function getRecurrenceRules() |
||
788 | |||
789 | /** |
||
790 | * @param $dtStamp |
||
791 | * |
||
792 | * @return $this |
||
793 | */ |
||
794 | public function setCreated($dtStamp) |
||
800 | |||
801 | /** |
||
802 | * @param $dtStamp |
||
803 | * |
||
804 | * @return $this |
||
805 | */ |
||
806 | public function setModified($dtStamp) |
||
812 | |||
813 | /** |
||
814 | * @param $categories |
||
815 | * |
||
816 | * @return $this |
||
817 | */ |
||
818 | public function setCategories($categories) |
||
824 | |||
825 | /** |
||
826 | * Sets the event privacy. |
||
827 | * |
||
828 | * @param bool $flag |
||
829 | * |
||
830 | * @return $this |
||
831 | */ |
||
832 | public function setIsPrivate($flag) |
||
838 | |||
839 | /** |
||
840 | * @param \DateTimeInterface $dateTime |
||
841 | * |
||
842 | * @return \Eluceo\iCal\Component\Event |
||
843 | */ |
||
844 | public function addExDate(\DateTimeInterface $dateTime) |
||
850 | |||
851 | /** |
||
852 | * @return \DateTimeInterface[] |
||
853 | */ |
||
854 | public function getExDates() |
||
858 | |||
859 | /** |
||
860 | * @param \DateTimeInterface[] |
||
861 | * |
||
862 | * @return \Eluceo\iCal\Component\Event |
||
863 | */ |
||
864 | public function setExDates(array $exDates) |
||
870 | |||
871 | /** |
||
872 | * @return \Eluceo\iCal\Property\Event\RecurrenceId |
||
873 | */ |
||
874 | public function getRecurrenceId() |
||
878 | |||
879 | /** |
||
880 | * @param RecurrenceId $recurrenceId |
||
881 | * |
||
882 | * @return \Eluceo\iCal\Component\Event |
||
883 | */ |
||
884 | public function setRecurrenceId(RecurrenceId $recurrenceId) |
||
890 | |||
891 | /** |
||
892 | * @param array $attachment |
||
893 | * |
||
894 | * @return $this |
||
895 | */ |
||
896 | 1 | public function addAttachment(Attachment $attachment) |
|
897 | { |
||
898 | 1 | $this->attachments[] = $attachment; |
|
899 | |||
900 | 1 | return $this; |
|
901 | } |
||
902 | |||
903 | /** |
||
904 | * @return array |
||
905 | */ |
||
906 | public function getAttachments() |
||
910 | |||
911 | /** |
||
912 | * @param string $url |
||
913 | */ |
||
914 | public function addUrlAttachment(string $url) |
||
918 | } |
||
919 |