Complex classes like Interval 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 Interval, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
57 | class Interval extends DateInterval |
||
58 | { |
||
59 | use DateLocalizationCapabilities; |
||
60 | /** |
||
61 | * Interval spec period designators. |
||
62 | */ |
||
63 | const PERIOD_PREFIX = 'P'; |
||
64 | const PERIOD_YEARS = 'Y'; |
||
65 | const PERIOD_MONTHS = 'M'; |
||
66 | const PERIOD_DAYS = 'D'; |
||
67 | const PERIOD_TIME_PREFIX = 'T'; |
||
68 | const PERIOD_HOURS = 'H'; |
||
69 | const PERIOD_MINUTES = 'M'; |
||
70 | const PERIOD_SECONDS = 'S'; |
||
71 | |||
72 | /** |
||
73 | * Before PHP 5.4.20/5.5.4 instead of FALSE days will be set to -99999 when the interval instance |
||
74 | * was created by DateTime:diff(). |
||
75 | */ |
||
76 | const PHP_DAYS_FALSE = -99999; |
||
77 | |||
78 | /** |
||
79 | * Determine if the interval was created via DateTime:diff() or not. |
||
80 | * |
||
81 | * @param DateInterval $interval |
||
82 | * |
||
83 | * @return bool |
||
84 | */ |
||
85 | private static function wasCreatedFromDiff(DateInterval $interval) |
||
89 | |||
90 | /////////////////////////////////////////////////////////////////// |
||
91 | //////////////////////////// CONSTRUCTORS ///////////////////////// |
||
92 | /////////////////////////////////////////////////////////////////// |
||
93 | |||
94 | /** |
||
95 | * Create a new Interval instance. |
||
96 | * |
||
97 | * @param int $years |
||
98 | * @param int $months |
||
99 | * @param int $weeks |
||
100 | * @param int $days |
||
101 | * @param int $hours |
||
102 | * @param int $minutes |
||
103 | * @param int $seconds |
||
104 | */ |
||
105 | public function __construct( |
||
139 | |||
140 | /** |
||
141 | * Create a new Interval instance from specific values. |
||
142 | * This is an alias for the constructor that allows better fluent |
||
143 | * syntax as it allows you to do Interval::create(1)->fn() rather than |
||
144 | * (new Interval(1))->fn(). |
||
145 | * |
||
146 | * @param int $years |
||
147 | * @param int $months |
||
148 | * @param int $weeks |
||
149 | * @param int $days |
||
150 | * @param int $hours |
||
151 | * @param int $minutes |
||
152 | * @param int $seconds |
||
153 | * |
||
154 | * @return static |
||
155 | */ |
||
156 | public static function create( |
||
167 | |||
168 | /** |
||
169 | * Provide static helpers to create instances. Allows Interval::years(3). |
||
170 | * |
||
171 | * Note: This is done using the magic method to allow static and instance methods to |
||
172 | * have the same names. |
||
173 | * |
||
174 | * @param string $name |
||
175 | * @param array $args |
||
176 | * |
||
177 | * @return static |
||
178 | */ |
||
179 | public static function __callStatic($name, $args) |
||
216 | |||
217 | /** |
||
218 | * Create a Interval instance from a DateInterval one. Can not instance |
||
219 | * Interval objects created from DateTime::diff() as you can't externally |
||
220 | * set the $days field. |
||
221 | * |
||
222 | * @param DateInterval|Interval $di |
||
223 | * |
||
224 | * @return static |
||
225 | */ |
||
226 | public static function instance(DateInterval $di) |
||
238 | |||
239 | /** |
||
240 | * @param string $intervalSpec |
||
241 | * |
||
242 | * @return Interval |
||
243 | */ |
||
244 | public static function createFromSpec($intervalSpec) |
||
250 | |||
251 | /////////////////////////////////////////////////////////////////// |
||
252 | ///////////////////////// GETTERS AND SETTERS ///////////////////// |
||
253 | /////////////////////////////////////////////////////////////////// |
||
254 | |||
255 | /** |
||
256 | * Get a part of the Interval object. |
||
257 | * |
||
258 | * @param string $name |
||
259 | * |
||
260 | * @throws InvalidArgumentException |
||
261 | * |
||
262 | * @return int |
||
263 | */ |
||
264 | public function __get($name) |
||
296 | |||
297 | /** |
||
298 | * Set a part of the Interval object. |
||
299 | * |
||
300 | * @param string $name |
||
301 | * @param int $val |
||
302 | * |
||
303 | * @throws InvalidArgumentException |
||
304 | */ |
||
305 | public function __set($name, $val) |
||
337 | |||
338 | /** |
||
339 | * Allow setting of weeks and days to be cumulative. |
||
340 | * |
||
341 | * @param int $weeks Number of weeks to set |
||
342 | * @param int $days Number of days to set |
||
343 | * |
||
344 | * @return static |
||
345 | */ |
||
346 | public function weeksAndDays($weeks, $days) |
||
352 | |||
353 | /** |
||
354 | * Allow fluent calls on the setters... Interval::years(3)->months(5)->day(). |
||
355 | * |
||
356 | * Note: This is done using the magic method to allow static and instance methods to |
||
357 | * have the same names. |
||
358 | * |
||
359 | * @param string $name |
||
360 | * @param array $args |
||
361 | * |
||
362 | * @return static |
||
363 | */ |
||
364 | public function __call($name, $args) |
||
408 | |||
409 | /** |
||
410 | * Get the current interval in a human readable format in the current locale. |
||
411 | * |
||
412 | * @return string |
||
413 | */ |
||
414 | public function forHumans() |
||
435 | |||
436 | /** |
||
437 | * Format the instance as a string using the forHumans() function. |
||
438 | * |
||
439 | * @return string |
||
440 | */ |
||
441 | public function __toString() |
||
445 | |||
446 | /** |
||
447 | * Add the passed interval to the current instance. |
||
448 | * |
||
449 | * @param DateInterval $interval |
||
450 | * |
||
451 | * @return static |
||
452 | */ |
||
453 | public function add(DateInterval $interval) |
||
470 | } |
||
471 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.