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) |
|
457 | |||
458 | /** |
||
459 | * @return $this |
||
460 | */ |
||
461 | 1 | public function setGeoLocation(Geo $geoProperty) |
|
467 | |||
468 | /** |
||
469 | * @param $noTime |
||
470 | * |
||
471 | * @return $this |
||
472 | */ |
||
473 | 1 | public function setNoTime($noTime) |
|
479 | |||
480 | /** |
||
481 | * @param int $sequence |
||
482 | * |
||
483 | * @return $this |
||
484 | */ |
||
485 | 2 | public function setSequence($sequence) |
|
491 | |||
492 | /** |
||
493 | * @return int |
||
494 | */ |
||
495 | 1 | public function getSequence() |
|
499 | |||
500 | /** |
||
501 | * @return $this |
||
502 | */ |
||
503 | 2 | public function setOrganizer(Organizer $organizer) |
|
509 | |||
510 | /** |
||
511 | * @param $summary |
||
512 | * |
||
513 | * @return $this |
||
514 | */ |
||
515 | 1 | public function setSummary($summary) |
|
521 | |||
522 | /** |
||
523 | * @param $uniqueId |
||
524 | * |
||
525 | * @return $this |
||
526 | */ |
||
527 | 1 | public function setUniqueId($uniqueId) |
|
533 | |||
534 | /** |
||
535 | * @return string |
||
536 | */ |
||
537 | 2 | public function getUniqueId() |
|
541 | |||
542 | /** |
||
543 | * @param $url |
||
544 | * |
||
545 | * @return $this |
||
546 | */ |
||
547 | 1 | public function setUrl($url) |
|
553 | |||
554 | /** |
||
555 | * @param $useTimezone |
||
556 | * |
||
557 | * @return $this |
||
558 | */ |
||
559 | public function setUseTimezone($useTimezone) |
||
565 | |||
566 | /** |
||
567 | * @return bool |
||
568 | */ |
||
569 | public function getUseTimezone() |
||
573 | |||
574 | /** |
||
575 | * @param $timezoneString |
||
576 | * |
||
577 | * @return $this |
||
578 | */ |
||
579 | 2 | public function setTimezoneString($timezoneString) |
|
585 | |||
586 | /** |
||
587 | * @return bool |
||
588 | */ |
||
589 | 1 | public function getTimezoneString() |
|
593 | |||
594 | /** |
||
595 | * @return $this |
||
596 | */ |
||
597 | public function setAttendees(Attendees $attendees) |
||
603 | |||
604 | /** |
||
605 | * @param string $attendee |
||
606 | * @param array $params |
||
607 | * |
||
608 | * @return $this |
||
609 | */ |
||
610 | public function addAttendee($attendee, $params = []) |
||
616 | |||
617 | public function getAttendees(): Attendees |
||
621 | |||
622 | /** |
||
623 | * @param $description |
||
624 | * |
||
625 | * @return $this |
||
626 | */ |
||
627 | 4 | public function setDescription($description) |
|
633 | |||
634 | /** |
||
635 | * @param $descriptionHTML |
||
636 | * |
||
637 | * @return $this |
||
638 | */ |
||
639 | public function setDescriptionHTML($descriptionHTML) |
||
645 | |||
646 | /** |
||
647 | * @param bool $useUtc |
||
648 | * |
||
649 | * @return $this |
||
650 | */ |
||
651 | public function setUseUtc($useUtc = true) |
||
657 | |||
658 | /** |
||
659 | * @return string |
||
660 | */ |
||
661 | public function getDescription() |
||
665 | |||
666 | /** |
||
667 | * @return string |
||
668 | */ |
||
669 | public function getDescriptionHTML() |
||
673 | |||
674 | /** |
||
675 | * @param $status |
||
676 | * |
||
677 | * @return $this |
||
678 | */ |
||
679 | public function setCancelled($status) |
||
685 | |||
686 | /** |
||
687 | * @param $transparency |
||
688 | * |
||
689 | * @return $this |
||
690 | * |
||
691 | * @throws \InvalidArgumentException |
||
692 | */ |
||
693 | View Code Duplication | public function setTimeTransparency($transparency) |
|
706 | |||
707 | /** |
||
708 | * @param $status |
||
709 | * |
||
710 | * @return $this |
||
711 | * |
||
712 | * @throws \InvalidArgumentException |
||
713 | */ |
||
714 | public function setStatus($status) |
||
728 | |||
729 | /** |
||
730 | * @deprecated Deprecated since version 0.11.0, to be removed in 1.0. Use addRecurrenceRule instead. |
||
731 | * |
||
732 | * @return $this |
||
733 | */ |
||
734 | public function setRecurrenceRule(RecurrenceRule $recurrenceRule) |
||
742 | |||
743 | /** |
||
744 | * @deprecated Deprecated since version 0.11.0, to be removed in 1.0. Use getRecurrenceRules instead. |
||
745 | * |
||
746 | * @return RecurrenceRule |
||
747 | */ |
||
748 | public function getRecurrenceRule() |
||
754 | |||
755 | /** |
||
756 | * @return $this |
||
757 | */ |
||
758 | public function addRecurrenceRule(RecurrenceRule $recurrenceRule) |
||
764 | |||
765 | /** |
||
766 | * @return array |
||
767 | */ |
||
768 | public function getRecurrenceRules() |
||
772 | |||
773 | /** |
||
774 | * @param $dtStamp |
||
775 | * |
||
776 | * @return $this |
||
777 | */ |
||
778 | public function setCreated($dtStamp) |
||
784 | |||
785 | /** |
||
786 | * @param $dtStamp |
||
787 | * |
||
788 | * @return $this |
||
789 | */ |
||
790 | public function setModified($dtStamp) |
||
796 | |||
797 | /** |
||
798 | * @param $categories |
||
799 | * |
||
800 | * @return $this |
||
801 | */ |
||
802 | public function setCategories($categories) |
||
808 | |||
809 | /** |
||
810 | * Sets the event privacy. |
||
811 | * |
||
812 | * @param bool $flag |
||
813 | * |
||
814 | * @return $this |
||
815 | */ |
||
816 | public function setIsPrivate($flag) |
||
822 | |||
823 | /** |
||
824 | * @return \Eluceo\iCal\Component\Event |
||
825 | */ |
||
826 | public function addExDate(\DateTimeInterface $dateTime) |
||
832 | |||
833 | /** |
||
834 | * @return \DateTimeInterface[] |
||
835 | */ |
||
836 | public function getExDates() |
||
840 | |||
841 | /** |
||
842 | * @param \DateTimeInterface[] |
||
843 | * |
||
844 | * @return \Eluceo\iCal\Component\Event |
||
845 | */ |
||
846 | public function setExDates(array $exDates) |
||
852 | |||
853 | /** |
||
854 | * @return \Eluceo\iCal\Property\Event\RecurrenceId |
||
855 | */ |
||
856 | public function getRecurrenceId() |
||
860 | |||
861 | /** |
||
862 | * @return \Eluceo\iCal\Component\Event |
||
863 | */ |
||
864 | public function setRecurrenceId(RecurrenceId $recurrenceId) |
||
870 | |||
871 | /** |
||
872 | * @param array $attachment |
||
873 | * |
||
874 | * @return $this |
||
875 | */ |
||
876 | 1 | public function addAttachment(Attachment $attachment) |
|
882 | |||
883 | /** |
||
884 | * @return array |
||
885 | */ |
||
886 | public function getAttachments() |
||
890 | |||
891 | public function addUrlAttachment(string $url) |
||
895 | } |
||
896 |