Complex classes like DateHandler 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 DateHandler, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 29 | class DateHandler implements SubscribingHandlerInterface |
||
| 30 | { |
||
| 31 | private $defaultFormat; |
||
| 32 | private $defaultTimezone; |
||
| 33 | private $xmlCData; |
||
| 34 | |||
| 35 | 387 | public static function getSubscribingMethods() |
|
| 36 | { |
||
| 37 | 387 | $methods = array(); |
|
| 38 | 387 | $deserializationTypes = array('DateTime', 'DateTimeImmutable', 'DateInterval'); |
|
| 39 | 387 | $serialisationTypes = array('DateTime', 'DateTimeImmutable', 'DateInterval'); |
|
| 40 | |||
| 41 | 387 | foreach (array('json', 'xml', 'yml') as $format) { |
|
| 42 | |||
| 43 | 387 | foreach ($deserializationTypes as $type) { |
|
| 44 | 387 | $methods[] = [ |
|
| 45 | 387 | 'type' => $type, |
|
| 46 | 387 | 'direction' => GraphNavigator::DIRECTION_DESERIALIZATION, |
|
| 47 | 387 | 'format' => $format, |
|
| 48 | ]; |
||
| 49 | } |
||
| 50 | |||
| 51 | 387 | foreach ($serialisationTypes as $type) { |
|
| 52 | 387 | $methods[] = array( |
|
| 53 | 387 | 'type' => $type, |
|
| 54 | 387 | 'format' => $format, |
|
| 55 | 387 | 'direction' => GraphNavigator::DIRECTION_SERIALIZATION, |
|
| 56 | 387 | 'method' => 'serialize' . $type, |
|
| 57 | ); |
||
| 58 | } |
||
| 59 | } |
||
| 60 | |||
| 61 | 387 | return $methods; |
|
| 62 | } |
||
| 63 | |||
| 64 | 395 | public function __construct($defaultFormat = \DateTime::ISO8601, $defaultTimezone = 'UTC', $xmlCData = true) |
|
| 70 | |||
| 71 | 30 | private function serializeDateTimeInterface( |
|
| 89 | |||
| 90 | 24 | public function serializeDateTime(VisitorInterface $visitor, \DateTime $date, array $type, Context $context) |
|
| 94 | |||
| 95 | 6 | public function serializeDateTimeImmutable( |
|
| 104 | |||
| 105 | 3 | public function serializeDateInterval(VisitorInterface $visitor, \DateInterval $date, array $type, Context $context) |
|
| 115 | |||
| 116 | 7 | private function isDataXmlNull($data) |
|
| 121 | |||
| 122 | 5 | public function deserializeDateTimeFromXml(XmlDeserializationVisitor $visitor, $data, array $type) |
|
|
|
|||
| 123 | { |
||
| 124 | 5 | if ($this->isDataXmlNull($data)) { |
|
| 125 | return null; |
||
| 126 | } |
||
| 127 | |||
| 128 | 5 | return $this->parseDateTime($data, $type); |
|
| 129 | } |
||
| 130 | |||
| 131 | 1 | public function deserializeDateTimeImmutableFromXml(XmlDeserializationVisitor $visitor, $data, array $type) |
|
| 139 | |||
| 140 | 1 | public function deserializeDateIntervalFromXml(XmlDeserializationVisitor $visitor, $data, array $type) |
|
| 148 | |||
| 149 | 10 | public function deserializeDateTimeFromJson(JsonDeserializationVisitor $visitor, $data, array $type) |
|
| 157 | |||
| 158 | 3 | public function deserializeDateTimeImmutableFromJson(JsonDeserializationVisitor $visitor, $data, array $type) |
|
| 166 | |||
| 167 | 1 | public function deserializeDateIntervalFromJson(JsonDeserializationVisitor $visitor, $data, array $type) |
|
| 175 | |||
| 176 | 18 | private function parseDateTime($data, array $type, $immutable = false) |
|
| 177 | { |
||
| 178 | 18 | $timezone = !empty($type['params'][1]) ? new \DateTimeZone($type['params'][1]) : $this->defaultTimezone; |
|
| 179 | 18 | $format = $this->getDeserializationFormat($type); |
|
| 180 | |||
| 181 | 18 | if ($immutable) { |
|
| 182 | 4 | $datetime = \DateTimeImmutable::createFromFormat($format, (string)$data, $timezone); |
|
| 183 | } else { |
||
| 184 | 14 | $datetime = \DateTime::createFromFormat($format, (string)$data, $timezone); |
|
| 185 | } |
||
| 186 | |||
| 187 | 18 | if (false === $datetime) { |
|
| 188 | throw new RuntimeException(sprintf('Invalid datetime "%s", expected format %s.', $data, $format)); |
||
| 189 | } |
||
| 190 | |||
| 191 | 18 | if ($format === 'U') { |
|
| 192 | 4 | $datetime = $datetime->setTimezone($timezone); |
|
| 193 | } |
||
| 194 | |||
| 195 | 18 | return $datetime; |
|
| 196 | } |
||
| 197 | |||
| 198 | 2 | private function parseDateInterval($data) |
|
| 199 | { |
||
| 200 | 2 | $dateInterval = null; |
|
| 201 | try { |
||
| 202 | 2 | $dateInterval = new \DateInterval($data); |
|
| 203 | } catch (\Exception $e) { |
||
| 204 | throw new RuntimeException(sprintf('Invalid dateinterval "%s", expected ISO 8601 format', $data), null, $e); |
||
| 205 | } |
||
| 206 | |||
| 207 | 2 | return $dateInterval; |
|
| 208 | } |
||
| 209 | |||
| 210 | /** |
||
| 211 | * @param array $type |
||
| 212 | * @return string |
||
| 213 | */ |
||
| 214 | 18 | private function getDeserializationFormat(array $type) |
|
| 224 | |||
| 225 | /** |
||
| 226 | * @return string |
||
| 227 | * @param array $type |
||
| 228 | */ |
||
| 229 | 30 | private function getFormat(array $type) |
|
| 233 | |||
| 234 | /** |
||
| 235 | * @param \DateInterval $dateInterval |
||
| 236 | * @return string |
||
| 237 | */ |
||
| 238 | 4 | public function format(\DateInterval $dateInterval) |
|
| 276 | } |
||
| 277 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.