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 Calendar 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 Calendar, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
23 | abstract class Calendar { |
||
24 | |||
25 | /** |
||
26 | * Calendar Id. |
||
27 | * |
||
28 | * @access public |
||
29 | * @var int |
||
30 | */ |
||
31 | public $id = 0; |
||
32 | |||
33 | /** |
||
34 | * Calendar post object. |
||
35 | * |
||
36 | * @access public |
||
37 | * @var \WP_Post |
||
38 | */ |
||
39 | public $post = null; |
||
40 | |||
41 | /** |
||
42 | * Calendar Type. |
||
43 | * |
||
44 | * @access public |
||
45 | * @var string |
||
46 | */ |
||
47 | public $type = ''; |
||
48 | |||
49 | /** |
||
50 | * Calendar Name. |
||
51 | * |
||
52 | * @access public |
||
53 | * @var string |
||
54 | */ |
||
55 | public $name = ''; |
||
56 | |||
57 | /** |
||
58 | * Feed type. |
||
59 | * |
||
60 | * @access public |
||
61 | * @var string |
||
62 | */ |
||
63 | public $feed = ''; |
||
64 | |||
65 | /** |
||
66 | * Calendar start. |
||
67 | * |
||
68 | * @access public |
||
69 | * @var int |
||
70 | */ |
||
71 | public $start = 0; |
||
72 | |||
73 | /** |
||
74 | * Calendar end. |
||
75 | * |
||
76 | * @access public |
||
77 | * @var int |
||
78 | */ |
||
79 | public $end = 0; |
||
80 | |||
81 | /** |
||
82 | * Static calendar. |
||
83 | * |
||
84 | * @access public |
||
85 | * @var bool |
||
86 | */ |
||
87 | public $static = false; |
||
88 | |||
89 | /** |
||
90 | * Today. |
||
91 | * |
||
92 | * @access public |
||
93 | * @var int |
||
94 | */ |
||
95 | public $today = 0; |
||
96 | |||
97 | /** |
||
98 | * Time now. |
||
99 | * |
||
100 | * @access public |
||
101 | * @var int |
||
102 | */ |
||
103 | public $now = 0; |
||
104 | |||
105 | /** |
||
106 | * Timezone offset. |
||
107 | * |
||
108 | * @access public |
||
109 | * @var int |
||
110 | */ |
||
111 | public $offset = 0; |
||
112 | |||
113 | /** |
||
114 | * Timezone |
||
115 | * |
||
116 | * @access public |
||
117 | * @var string |
||
118 | */ |
||
119 | public $timezone = 'UTC'; |
||
120 | |||
121 | /** |
||
122 | * Site timezone. |
||
123 | * |
||
124 | * @access public |
||
125 | * @var string |
||
126 | */ |
||
127 | public $site_timezone = 'UTC'; |
||
128 | |||
129 | /** |
||
130 | * Date format. |
||
131 | * |
||
132 | * @access public |
||
133 | * @var string |
||
134 | */ |
||
135 | public $date_format = ''; |
||
136 | |||
137 | /** |
||
138 | * Time format. |
||
139 | * |
||
140 | * @access public |
||
141 | * @var string |
||
142 | */ |
||
143 | public $time_format = ''; |
||
144 | |||
145 | /** |
||
146 | * Date-time separator. |
||
147 | * |
||
148 | * @access public |
||
149 | * @var string |
||
150 | */ |
||
151 | public $datetime_separator = '@'; |
||
152 | |||
153 | /** |
||
154 | * First day of the week. |
||
155 | * |
||
156 | * @access public |
||
157 | * @var int |
||
158 | */ |
||
159 | public $week_starts = 0; |
||
160 | |||
161 | /** |
||
162 | * Events to display. |
||
163 | * |
||
164 | * @access public |
||
165 | * @var array |
||
166 | */ |
||
167 | public $events = array(); |
||
168 | |||
169 | /** |
||
170 | * Errors. |
||
171 | * |
||
172 | * @access public |
||
173 | * @var array |
||
174 | */ |
||
175 | protected $errors = array(); |
||
176 | |||
177 | /** |
||
178 | * Earliest event. |
||
179 | * |
||
180 | * @access public |
||
181 | * @var int |
||
182 | */ |
||
183 | public $earliest_event = 0; |
||
184 | |||
185 | /** |
||
186 | * Latest event. |
||
187 | * |
||
188 | * @access public |
||
189 | * @var int |
||
190 | */ |
||
191 | public $latest_event = 0; |
||
192 | |||
193 | /** |
||
194 | * Event builder content. |
||
195 | * |
||
196 | * @access public |
||
197 | * @var string |
||
198 | */ |
||
199 | public $events_template = ''; |
||
200 | |||
201 | /** |
||
202 | * Calendar Views. |
||
203 | * |
||
204 | * The calendar available views. |
||
205 | * |
||
206 | * @access public |
||
207 | * @var array |
||
208 | */ |
||
209 | public $views = array(); |
||
210 | |||
211 | /** |
||
212 | * Calendar View. |
||
213 | * |
||
214 | * The current view. |
||
215 | * |
||
216 | * @access public |
||
217 | * @var Calendar_View |
||
218 | */ |
||
219 | public $view = null; |
||
220 | |||
221 | /** |
||
222 | * Calendar settings. |
||
223 | * |
||
224 | * @access protected |
||
225 | * @var array |
||
226 | */ |
||
227 | protected $settings = array(); |
||
228 | |||
229 | /** |
||
230 | * Constructor. |
||
231 | * |
||
232 | * @since 3.0.0 |
||
233 | * |
||
234 | * @param int|object|\WP_Post|Calendar $calendar |
||
235 | * @param string $view |
||
236 | */ |
||
237 | public function __construct( $calendar, $view = '' ) { |
||
307 | |||
308 | /** |
||
309 | * Overloading __isset function with post meta. |
||
310 | * |
||
311 | * @since 3.0.0 |
||
312 | * |
||
313 | * @param mixed $key Post meta key. |
||
314 | * |
||
315 | * @return bool |
||
316 | */ |
||
317 | public function __isset( $key ) { |
||
320 | |||
321 | /** |
||
322 | * Overloading __get function with post meta. |
||
323 | * |
||
324 | * @since 3.0.0 |
||
325 | * |
||
326 | * @param string $key Post meta key. |
||
327 | * |
||
328 | * @return mixed |
||
329 | */ |
||
330 | public function __get( $key ) { |
||
337 | |||
338 | /** |
||
339 | * Set post object and id. |
||
340 | * |
||
341 | * @since 3.0.0 |
||
342 | * |
||
343 | * @param int|object|\WP_Post|Calendar $calendar |
||
344 | */ |
||
345 | public function set_post_object( $calendar ) { |
||
360 | |||
361 | /** |
||
362 | * Return the calendar title. |
||
363 | * |
||
364 | * @since 3.0.0 |
||
365 | * |
||
366 | * @return string |
||
367 | */ |
||
368 | public function get_title() { |
||
372 | |||
373 | /** |
||
374 | * Get the calendar post data. |
||
375 | * |
||
376 | * @since 3.0.0 |
||
377 | * |
||
378 | * @return \WP_Post |
||
379 | */ |
||
380 | public function get_post_data() { |
||
383 | |||
384 | /** |
||
385 | * Set taxonomies. |
||
386 | * |
||
387 | * @since 3.0.0 |
||
388 | * @access protected |
||
389 | */ |
||
390 | protected function set_taxonomies() { |
||
404 | |||
405 | /** |
||
406 | * Get events. |
||
407 | * |
||
408 | * @since 3.0.0 |
||
409 | * |
||
410 | * @return Events |
||
411 | */ |
||
412 | public function get_events() { |
||
415 | |||
416 | /** |
||
417 | * Set events. |
||
418 | * |
||
419 | * @since 3.0.0 |
||
420 | * |
||
421 | * @param array $array |
||
422 | */ |
||
423 | public function set_events( array $array ) { |
||
437 | |||
438 | /** |
||
439 | * Get the event builder template. |
||
440 | * |
||
441 | * @since 3.0.0 |
||
442 | * |
||
443 | * @param string $template |
||
444 | * |
||
445 | * @return string |
||
446 | */ |
||
447 | public function set_events_template( $template = '' ) { |
||
469 | |||
470 | /** |
||
471 | * Set the timezone. |
||
472 | * |
||
473 | * @since 3.0.0 |
||
474 | * |
||
475 | * @param string $tz Timezone. |
||
476 | */ |
||
477 | public function set_timezone( $tz = '' ) { |
||
478 | |||
479 | $site_tz = esc_attr( simcal_get_wp_timezone() ); |
||
480 | |||
481 | if ( $this->feed === 'grouped-calendars' ) { |
||
482 | $this->timezone = $site_tz; |
||
483 | return; |
||
484 | } |
||
485 | |||
486 | if ( empty( $tz ) ) { |
||
487 | |||
488 | $timezone_setting = get_post_meta( $this->id, '_feed_timezone_setting', true ); |
||
489 | |||
490 | if ( 'use_site' == $timezone_setting ) { |
||
491 | $tz = $site_tz; |
||
492 | } elseif ( 'use_custom' == $timezone_setting ) { |
||
493 | $custom_timezone = esc_attr( get_post_meta( $this->id, '_feed_timezone', true ) ); |
||
494 | // One may be using a non standard timezone in GMT (UTC) offset format. |
||
495 | if ( ( strpos( $custom_timezone, 'UTC+' ) === 0 ) || ( strpos( $custom_timezone, 'UTC-' ) === 0 ) ) { |
||
496 | $tz = simcal_get_timezone_from_gmt_offset( substr( $custom_timezone, 3 ) ); |
||
497 | } else { |
||
498 | $tz = ! empty( $custom_timezone ) ? $custom_timezone : 'UTC'; |
||
499 | } |
||
500 | } |
||
501 | |||
502 | $this->timezone = empty( $tz ) ? 'UTC' : $tz; |
||
503 | return; |
||
504 | } |
||
505 | |||
506 | $this->site_timezone = $site_tz; |
||
507 | $this->timezone = simcal_esc_timezone( $tz, $this->timezone ); |
||
508 | } |
||
509 | |||
510 | /** |
||
511 | * Set date format. |
||
512 | * |
||
513 | * @since 3.0.0 |
||
514 | * |
||
515 | * @param string $format PHP datetime format. |
||
516 | */ |
||
517 | View Code Duplication | public function set_date_format( $format = '' ) { |
|
518 | |||
519 | $date_format_custom = $date_format_default = $format; |
||
520 | |||
521 | if ( empty( $date_format_custom ) ) { |
||
522 | |||
523 | $date_format_option = esc_attr( get_post_meta( $this->id, '_calendar_date_format_setting', true ) ); |
||
524 | $date_format_default = esc_attr( get_option( 'date_format' ) ); |
||
525 | $date_format_custom = ''; |
||
526 | |||
527 | if ( 'use_custom' == $date_format_option ) { |
||
528 | $date_format_custom = esc_attr( get_post_meta( $this->id, '_calendar_date_format', true ) ); |
||
529 | } elseif ( 'use_custom_php' == $date_format_option ) { |
||
530 | $date_format_custom = esc_attr( get_post_meta( $this->id, '_calendar_date_format_php', true ) ); |
||
531 | } |
||
532 | } |
||
533 | |||
534 | $this->date_format = $date_format_custom ? $date_format_custom : $date_format_default; |
||
535 | } |
||
536 | |||
537 | /** |
||
538 | * Set time format. |
||
539 | * |
||
540 | * @since 3.0.0 |
||
541 | * |
||
542 | * @param string $format PHP datetime format. |
||
543 | */ |
||
544 | View Code Duplication | public function set_time_format( $format = '' ) { |
|
545 | |||
546 | $time_format_custom = $time_format_default = $format; |
||
547 | |||
548 | if ( empty( $time_format_custom ) ) { |
||
549 | |||
550 | $time_format_option = esc_attr( get_post_meta( $this->id, '_calendar_time_format_setting', true ) ); |
||
551 | $time_format_default = esc_attr( get_option( 'time_format' ) ); |
||
552 | $time_format_custom = ''; |
||
553 | |||
554 | if ( 'use_custom' == $time_format_option ) { |
||
555 | $time_format_custom = esc_attr( get_post_meta( $this->id, '_calendar_time_format', true ) ); |
||
556 | } elseif ( 'use_custom_php' == $time_format_option ) { |
||
557 | $time_format_custom = esc_attr( get_post_meta( $this->id, '_calendar_time_format_php', true ) ); |
||
558 | } |
||
559 | } |
||
560 | |||
561 | $this->time_format = $time_format_custom ? $time_format_custom : $time_format_default; |
||
562 | } |
||
563 | |||
564 | /** |
||
565 | * Set date-time separator. |
||
566 | * |
||
567 | * @since 3.0.0 |
||
568 | * |
||
569 | * @param string $separator A UTF8 character used as separator. |
||
570 | */ |
||
571 | public function set_datetime_separator( $separator = '' ) { |
||
579 | |||
580 | /** |
||
581 | * Set start of week. |
||
582 | * |
||
583 | * @since 3.0.0 |
||
584 | * |
||
585 | * @param int $weekday From 0 (Sunday) to 6 (Friday). |
||
586 | */ |
||
587 | public function set_start_of_week( $weekday = -1 ) { |
||
604 | |||
605 | /** |
||
606 | * Set calendar start. |
||
607 | * |
||
608 | * @since 3.0.0 |
||
609 | * |
||
610 | * @param int $timestamp |
||
611 | */ |
||
612 | public function set_start( $timestamp = 0 ) { |
||
613 | |||
614 | if ( is_int( $timestamp ) && $timestamp !== 0 ) { |
||
615 | $this->start = $timestamp; |
||
616 | return; |
||
617 | } |
||
618 | |||
619 | $this->start = Carbon::now( $this->timezone )->getTimestamp(); |
||
620 | |||
621 | $calendar_begins = esc_attr( get_post_meta( $this->id, '_calendar_begins', true ) ); |
||
622 | $nth = max( absint( get_post_meta( $this->id, '_calendar_begins_nth', true ) ), 1 ); |
||
623 | |||
624 | if ( 'today' == $calendar_begins ) { |
||
625 | $this->start = Carbon::today( $this->timezone )->getTimestamp(); |
||
626 | } elseif ( 'days_before' == $calendar_begins ) { |
||
627 | $this->start = Carbon::today( $this->timezone )->subDays( $nth )->getTimestamp(); |
||
628 | } elseif ( 'days_after' == $calendar_begins ) { |
||
629 | $this->start = Carbon::today( $this->timezone )->addDays( $nth )->getTimestamp(); |
||
630 | View Code Duplication | } elseif ( 'this_week' == $calendar_begins ) { |
|
631 | $week = new Carbon( 'now', $this->timezone ); |
||
632 | $week->setWeekStartsAt( $this->week_starts ); |
||
633 | $this->start = $week->startOfWeek()->getTimestamp(); |
||
634 | } elseif ( 'weeks_before' == $calendar_begins ) { |
||
635 | $week = new Carbon( 'now', $this->timezone ); |
||
636 | $week->setWeekStartsAt( $this->week_starts ); |
||
637 | $this->start = $week->startOfWeek()->subWeeks( $nth )->getTimestamp(); |
||
638 | View Code Duplication | } elseif ( 'weeks_after' == $calendar_begins ) { |
|
639 | $week = new Carbon( 'now', $this->timezone ); |
||
640 | $week->setWeekStartsAt( $this->week_starts ); |
||
641 | $this->start = $week->startOfWeek()->addWeeks( $nth )->getTimestamp(); |
||
642 | } elseif ( 'this_month' == $calendar_begins ) { |
||
643 | $this->start = Carbon::today( $this->timezone )->startOfMonth()->getTimeStamp(); |
||
644 | } elseif ( 'months_before' == $calendar_begins ) { |
||
645 | $this->start = Carbon::today( $this->timezone )->subMonths( $nth )->startOfMonth()->getTimeStamp(); |
||
646 | } elseif ( 'months_after' == $calendar_begins ) { |
||
647 | $this->start = Carbon::today( $this->timezone )->addMonths( $nth )->startOfMonth()->getTimeStamp(); |
||
648 | } elseif ( 'this_year' == $calendar_begins ) { |
||
649 | $this->start = Carbon::today( $this->timezone )->startOfYear()->getTimestamp(); |
||
650 | } elseif ( 'years_before' == $calendar_begins ) { |
||
651 | $this->start = Carbon::today( $this->timezone )->subYears( $nth )->startOfYear()->getTimeStamp(); |
||
652 | } elseif ( 'years_after' == $calendar_begins ) { |
||
653 | $this->start = Carbon::today( $this->timezone )->addYears( $nth )->startOfYear()->getTimeStamp(); |
||
654 | } elseif ( 'custom_date' == $calendar_begins ) { |
||
655 | if ( $date = get_post_meta( $this->id, '_calendar_begins_custom_date', true ) ) { |
||
656 | $this->start = Carbon::createFromFormat( 'Y-m-d', esc_attr( $date ), $this->timezone )->setTimezone( $this->timezone )->startOfDay()->getTimestamp(); |
||
657 | } |
||
658 | } |
||
659 | } |
||
660 | |||
661 | /** |
||
662 | * Set calendar end. |
||
663 | * |
||
664 | * @since 3.0.0 |
||
665 | * |
||
666 | * @param int $timestamp |
||
667 | */ |
||
668 | public function set_end( $timestamp = 0 ) { |
||
672 | |||
673 | /** |
||
674 | * Set the calendar to static. |
||
675 | * |
||
676 | * @since 3.0.0 |
||
677 | * |
||
678 | * @param string|bool $static |
||
679 | */ |
||
680 | public function set_static( $static = '' ) { |
||
694 | |||
695 | /** |
||
696 | * Input fields for settings page. |
||
697 | * |
||
698 | * @since 3.0.0 |
||
699 | * |
||
700 | * @return array |
||
701 | */ |
||
702 | public function settings_fields() { |
||
705 | |||
706 | /** |
||
707 | * Get a calendar view. |
||
708 | * |
||
709 | * @since 3.0.0 |
||
710 | * |
||
711 | * @param string $view |
||
712 | * |
||
713 | * @return Calendar_View |
||
714 | */ |
||
715 | abstract public function get_view( $view = '' ); |
||
716 | |||
717 | /** |
||
718 | * Get event HTML parsed by template. |
||
719 | * |
||
720 | * @since 3.0.0 |
||
721 | * |
||
722 | * @param Event $event Event object to be parsed. |
||
723 | * @param string $template (optional) To use another template or a partial. |
||
724 | * |
||
725 | * @return string |
||
726 | */ |
||
727 | public function get_event_html( Event $event, $template = '' ) { |
||
733 | |||
734 | /** |
||
735 | * Get "Add to Google Calendar" link. |
||
736 | * |
||
737 | * @since 3.1.3 |
||
738 | * |
||
739 | * @param Event $event Event object to be parsed. |
||
740 | * |
||
741 | * @return string |
||
742 | */ |
||
743 | public function get_add_to_gcal_url( Event $event ) { |
||
778 | |||
779 | /** |
||
780 | * Output the calendar markup. |
||
781 | * |
||
782 | * @since 3.0.0 |
||
783 | * |
||
784 | * @param string $view The calendar view to display. |
||
785 | */ |
||
786 | public function html( $view = '' ) { |
||
848 | |||
849 | } |
||
850 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.