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 Date 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 Date, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
30 | class Date |
||
31 | { |
||
32 | /** constants */ |
||
33 | const CALENDAR_WINDOWS_1900 = 1900; // Base date of 1st Jan 1900 = 1.0 |
||
34 | const CALENDAR_MAC_1904 = 1904; // Base date of 2nd Jan 1904 = 1.0 |
||
35 | |||
36 | /* |
||
37 | * Names of the months of the year, indexed by shortname |
||
38 | * Planned usage for locale settings |
||
39 | * |
||
40 | * @public |
||
41 | * @var string[] |
||
42 | */ |
||
43 | public static $monthNames = [ |
||
44 | 'Jan' => 'January', |
||
45 | 'Feb' => 'February', |
||
46 | 'Mar' => 'March', |
||
47 | 'Apr' => 'April', |
||
48 | 'May' => 'May', |
||
49 | 'Jun' => 'June', |
||
50 | 'Jul' => 'July', |
||
51 | 'Aug' => 'August', |
||
52 | 'Sep' => 'September', |
||
53 | 'Oct' => 'October', |
||
54 | 'Nov' => 'November', |
||
55 | 'Dec' => 'December', |
||
56 | ]; |
||
57 | |||
58 | /* |
||
59 | * @public |
||
60 | * @var string[] |
||
61 | */ |
||
62 | public static $numberSuffixes = [ |
||
63 | 'st', |
||
64 | 'nd', |
||
65 | 'rd', |
||
66 | 'th', |
||
67 | ]; |
||
68 | |||
69 | /* |
||
70 | * Base calendar year to use for calculations |
||
71 | * Value is either CALENDAR_WINDOWS_1900 (1900) or CALENDAR_MAC_1904 (1904) |
||
72 | * |
||
73 | * @private |
||
74 | * @var int |
||
75 | */ |
||
76 | protected static $excelCalendar = self::CALENDAR_WINDOWS_1900; |
||
77 | |||
78 | /* |
||
79 | * Default timezone to use for DateTime objects |
||
80 | * |
||
81 | * @private |
||
82 | * @var null|\DateTimeZone |
||
83 | */ |
||
84 | protected static $defaultTimeZone; |
||
85 | |||
86 | /** |
||
87 | * Set the Excel calendar (Windows 1900 or Mac 1904) |
||
88 | * |
||
89 | * @param integer $baseDate Excel base date (1900 or 1904) |
||
90 | * @return boolean Success or failure |
||
91 | */ |
||
92 | public static function setExcelCalendar($baseDate) |
||
101 | |||
102 | /** |
||
103 | * Return the Excel calendar (Windows 1900 or Mac 1904) |
||
104 | * |
||
105 | * @return integer Excel base date (1900 or 1904) |
||
106 | */ |
||
107 | public static function getExcelCalendar() |
||
111 | |||
112 | /** |
||
113 | * Set the Default timezone to use for dates |
||
114 | * |
||
115 | * @param string|\DateTimeZone $timezone The timezone to set for all Excel datetimestamp to PHP DateTime Object conversions |
||
|
|||
116 | * @return boolean Success or failure |
||
117 | * @throws \Exception |
||
118 | */ |
||
119 | public static function setDefaultTimezone($timeZone) |
||
127 | |||
128 | /** |
||
129 | * Return the Default timezone being used for dates |
||
130 | * |
||
131 | * @return \DateTimeZone The timezone being used as default for Excel timestamp to PHP DateTime object |
||
132 | */ |
||
133 | public static function getDefaultTimezone() |
||
140 | |||
141 | /** |
||
142 | * Validate a timezone |
||
143 | * |
||
144 | * @param string|\DateTimeZone $timezone The timezone to validate, either as a timezone string or object |
||
145 | * @return \DateTimeZone The timezone as a timezone object |
||
146 | * @throws \Exception |
||
147 | */ |
||
148 | protected static function validateTimeZone($timeZone) |
||
157 | |||
158 | /** |
||
159 | * Convert a MS serialized datetime value from Excel to a PHP Date/Time object |
||
160 | * |
||
161 | * @param integer|float $dateValue MS Excel serialized date/time value |
||
162 | * @param \DateTimeZone|string|null $timezone The timezone to assume for the Excel timestamp, |
||
163 | * if you don't want to treat it as a UTC value |
||
164 | * Use the default (UST) unless you absolutely need a conversion |
||
165 | * @return \DateTime PHP date/time object |
||
166 | * @throws \Exception |
||
167 | */ |
||
168 | public static function excelToDateTimeObject($excelTimestamp = 0, $timeZone = null) |
||
195 | |||
196 | /** |
||
197 | * Convert a MS serialized datetime value from Excel to a unix timestamp |
||
198 | * |
||
199 | * @param integer|float $dateValue MS Excel serialized date/time value |
||
200 | * @param \DateTimeZone|string|null $timezone The timezone to assume for the Excel timestamp, |
||
201 | * if you don't want to treat it as a UTC value |
||
202 | * Use the default (UST) unless you absolutely need a conversion |
||
203 | * @return integer Unix timetamp for this date/time |
||
204 | * @throws \Exception |
||
205 | */ |
||
206 | public static function excelToTimestamp($excelTimestamp = 0, $timeZone = null) |
||
211 | |||
212 | |||
213 | /** |
||
214 | * Convert a date from PHP to Excel |
||
215 | * |
||
216 | * @param mixed $dateValue PHP serialized date/time or date object |
||
217 | * @param boolean $adjustToTimezone Flag indicating whether $dateValue should be treated as |
||
218 | * a UST timestamp, or adjusted to UST |
||
219 | * @param string $timezone The timezone for finding the adjustment from UST |
||
220 | * @return mixed Excel date/time value |
||
221 | * or boolean FALSE on failure |
||
222 | */ |
||
223 | public static function PHPToExcel($dateValue = 0, $adjustToTimezone = false, $timezone = null) |
||
246 | |||
247 | |||
248 | /** |
||
249 | * formattedPHPToExcel |
||
250 | * |
||
251 | * @param integer $year |
||
252 | * @param integer $month |
||
253 | * @param integer $day |
||
254 | * @param integer $hours |
||
255 | * @param integer $minutes |
||
256 | * @param integer $seconds |
||
257 | * @return integer Excel date/time value |
||
258 | */ |
||
259 | public static function formattedPHPToExcel($year, $month, $day, $hours = 0, $minutes = 0, $seconds = 0) |
||
293 | |||
294 | |||
295 | /** |
||
296 | * Is a given cell a date/time? |
||
297 | * |
||
298 | * @param \PHPExcel\Cell $pCell |
||
299 | * @return boolean |
||
300 | */ |
||
301 | public static function isDateTime(\PHPExcel\Cell $pCell) |
||
309 | |||
310 | |||
311 | /** |
||
312 | * Is a given number format a date/time? |
||
313 | * |
||
314 | * @param \PHPExcel\Style\NumberFormat $pFormat |
||
315 | * @return boolean |
||
316 | */ |
||
317 | public static function isDateTimeFormat(\PHPExcel\Style\NumberFormat $pFormat) |
||
321 | |||
322 | |||
323 | private static $possibleDateFormatCharacters = 'eymdHs'; |
||
324 | |||
325 | /** |
||
326 | * Is a given number format code a date/time? |
||
327 | * |
||
328 | * @param string $pFormatCode |
||
329 | * @return boolean |
||
330 | */ |
||
331 | public static function isDateTimeFormatCode($pFormatCode = '') |
||
395 | |||
396 | |||
397 | /** |
||
398 | * Convert a date/time string to Excel time |
||
399 | * |
||
400 | * @param string $dateValue Examples: '2009-12-31', '2009-12-31 15:59', '2009-12-31 15:59:10' |
||
401 | * @return float|FALSE Excel date/time serial value |
||
402 | */ |
||
403 | public static function stringToExcel($dateValue = '') |
||
427 | |||
428 | /** |
||
429 | * Converts a month name (either a long or a short name) to a month number |
||
430 | * |
||
431 | * @param string $month Month name or abbreviation |
||
432 | * @return integer|string Month number (1 - 12), or the original string argument if it isn't a valid month name |
||
433 | */ |
||
434 | public static function monthStringToNumber($month) |
||
445 | |||
446 | /** |
||
447 | * Strips an ordinal froma numeric value |
||
448 | * |
||
449 | * @param string $day Day number with an ordinal |
||
450 | * @return integer|string The integer value with any ordinal stripped, or the original string argument if it isn't a valid numeric |
||
451 | */ |
||
452 | public static function dayStringToNumber($day) |
||
460 | } |
||
461 |
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.
Consider the following example. The parameter
$ireland
is not defined by the methodfinale(...)
.The most likely cause is that the parameter was changed, but the annotation was not.