Total Complexity | 46 |
Total Lines | 260 |
Duplicated Lines | 0 % |
Changes | 2 | ||
Bugs | 1 | Features | 0 |
Complex classes like Address 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.
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 Address, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
17 | class Address |
||
18 | { |
||
19 | /** |
||
20 | * @var DataBag; |
||
21 | */ |
||
22 | protected $dataBag; |
||
23 | |||
24 | protected function __construct(array $addressData = []) |
||
25 | { |
||
26 | $this->dataBag = DataBag::create(); |
||
27 | if ($addressData === []) { |
||
28 | return; |
||
29 | } |
||
30 | $this->dataBag->addEntityData('address', $addressData); |
||
31 | } |
||
32 | |||
33 | /** |
||
34 | * @return static |
||
35 | */ |
||
36 | public static function create() |
||
37 | { |
||
38 | return new static(); |
||
39 | } |
||
40 | |||
41 | /** |
||
42 | * @return static |
||
43 | */ |
||
44 | public static function fromAddressData(array $addressData = null) |
||
45 | { |
||
46 | if ($addressData === null) { |
||
47 | $addressData = []; |
||
48 | } |
||
49 | return new static($addressData); |
||
50 | } |
||
51 | |||
52 | public function getProperty(): string |
||
53 | { |
||
54 | return (string)$this->dataBag->get('address.property'); |
||
55 | } |
||
56 | |||
57 | public function setProperty(string $property): void |
||
60 | } |
||
61 | |||
62 | public function getStreet(): string |
||
63 | { |
||
64 | return trim((string)$this->dataBag->get('address.street')); |
||
65 | } |
||
66 | |||
67 | public function setStreet(string $street): void |
||
68 | { |
||
69 | $this->dataBag->set('address.street', $street); |
||
70 | } |
||
71 | |||
72 | public function getStreetNumber(): string |
||
73 | { |
||
74 | return (string)$this->dataBag->get('address.streetNumber'); |
||
75 | } |
||
76 | |||
77 | public function setStreetNumber(string $streetNumber): void |
||
78 | { |
||
79 | $this->dataBag->set('address.streetNumber', $streetNumber); |
||
80 | } |
||
81 | |||
82 | public function getStreetNumberAddition(): string |
||
83 | { |
||
84 | return (string)$this->dataBag->get('address.streetNumberAddition'); |
||
85 | } |
||
86 | |||
87 | public function setStreetNumberAddition(string $streetNumberAddition): void |
||
88 | { |
||
89 | $this->dataBag->set('address.streetNumberAddition', $streetNumberAddition); |
||
90 | } |
||
91 | |||
92 | public function getZipcode(): string |
||
93 | { |
||
94 | return trim((string)$this->dataBag->get('address.zipcode')); |
||
95 | } |
||
96 | |||
97 | public function setZipcode(string $zipcode): void |
||
98 | { |
||
99 | $this->dataBag->set('address.zipcode', $zipcode); |
||
100 | } |
||
101 | |||
102 | public function getCity(): string |
||
103 | { |
||
104 | return trim((string)$this->dataBag->get('address.city')); |
||
105 | } |
||
106 | |||
107 | public function setCity(string $city): void |
||
108 | { |
||
109 | $this->dataBag->set('address.city', $city); |
||
110 | } |
||
111 | |||
112 | public function getCountryCode(string $default = 'NL'): string |
||
113 | { |
||
114 | return trim((string)$this->dataBag->get('address.countryCode', $default)); |
||
115 | } |
||
116 | |||
117 | public function setCountryCode(string $countryCode): void |
||
118 | { |
||
119 | $this->dataBag->set('address.countryCode', $countryCode); |
||
120 | } |
||
121 | |||
122 | public function getType(): string |
||
123 | { |
||
124 | return trim((string)$this->dataBag->get('address.type')); |
||
125 | } |
||
126 | |||
127 | public function setType(string $type): void |
||
130 | } |
||
131 | |||
132 | public function getId(): CommunibaseId |
||
133 | { |
||
134 | return CommunibaseId::fromString($this->dataBag->get('address._id')); |
||
135 | } |
||
136 | |||
137 | public function __toString() |
||
138 | { |
||
139 | return $this->toString(); |
||
140 | } |
||
141 | |||
142 | public function toString(bool $singleLine = true): string |
||
143 | { |
||
144 | if ($this->getState() === null) { |
||
145 | return ''; |
||
146 | } |
||
147 | $lines = [ |
||
148 | array_filter([$this->getStreet(), $this->getStreetNumber(), $this->getStreetNumberAddition()]), |
||
149 | array_filter([$this->getZipcode(), $this->getCity()]), |
||
150 | ]; |
||
151 | |||
152 | if ($singleLine) { |
||
153 | return implode( |
||
154 | ', ', |
||
155 | array_filter( |
||
156 | [ |
||
157 | implode(' ', $lines[0]), |
||
158 | implode(', ', $lines[1]), |
||
159 | ] |
||
160 | ) |
||
161 | ); |
||
162 | } |
||
163 | return implode( |
||
164 | PHP_EOL, |
||
165 | array_filter( |
||
166 | [ |
||
167 | implode(' ', $lines[0]), |
||
168 | implode(' ', $lines[1]), |
||
169 | ] |
||
170 | ) |
||
171 | ); |
||
172 | } |
||
173 | |||
174 | /** |
||
175 | * @return float[]|null |
||
176 | */ |
||
177 | public function getGeoLocation(): ?array |
||
178 | { |
||
179 | // native geo handling |
||
180 | if ($this->isGeoStorageUsingNativePoint()) { |
||
181 | $point = $this->dataBag->get('address.point'); |
||
182 | if (empty($point) || empty($point['coordinates']) || empty($point['coordinates'][0]) || empty($point['coordinates'][1])) { |
||
183 | return null; |
||
184 | } |
||
185 | return [ |
||
186 | 'lat' => (float)$point['coordinates'][1], |
||
187 | 'lng' => (float)$point['coordinates'][0], |
||
188 | ]; |
||
189 | } |
||
190 | |||
191 | // `old`-style |
||
192 | $lat = $this->dataBag->get('address.latitude'); |
||
193 | $lng = $this->dataBag->get('address.longitude'); |
||
194 | if (!isset($lat, $lng)) { |
||
195 | return null; |
||
196 | } |
||
197 | return [ |
||
198 | 'lat' => (float)$lat, |
||
199 | 'lng' => (float)$lng, |
||
200 | ]; |
||
201 | } |
||
202 | |||
203 | /** |
||
204 | * @throws InvalidGeoLocationException |
||
205 | */ |
||
206 | public function setGeoLocation(float $latitude, float $longitude): void |
||
225 | } |
||
226 | |||
227 | private function isGeoStorageUsingNativePoint(): bool |
||
228 | { |
||
229 | return !empty($this->dataBag->get('address.point')); |
||
230 | } |
||
231 | |||
232 | /** |
||
233 | * @return bool |
||
234 | */ |
||
235 | public function isEmpty(): bool |
||
244 | ] |
||
245 | ) |
||
246 | ); |
||
247 | } |
||
248 | |||
249 | public function __clone() |
||
250 | { |
||
251 | $state = $this->getState(); |
||
252 | if ($state !== null) { |
||
253 | unset($state['_id']); |
||
254 | $this->dataBag->addEntityData('address', $state); |
||
255 | } |
||
256 | } |
||
257 | |||
258 | /** |
||
259 | * @return array|null |
||
260 | */ |
||
261 | public function getState(): ?array |
||
267 | } |
||
268 | |||
269 | /** |
||
270 | * @throws InvalidGeoLocationException |
||
271 | */ |
||
272 | protected function guardAgainstInvalidLatLong(float $latitude, float $longitude): void |
||
281 |