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:
1 | <?php namespace Propaganistas\LaravelPhone; |
||
19 | class PhoneNumber implements Jsonable, JsonSerializable, Serializable |
||
20 | { |
||
21 | use ParsesCountries, |
||
22 | ParsesFormats, |
||
23 | ParsesTypes; |
||
24 | |||
25 | /** |
||
26 | * The provided phone number. |
||
27 | * |
||
28 | * @var string |
||
29 | */ |
||
30 | protected $number; |
||
31 | |||
32 | /** |
||
33 | * The provided phone country. |
||
34 | * |
||
35 | * @var array |
||
36 | */ |
||
37 | protected $countries = []; |
||
38 | |||
39 | /** |
||
40 | * The detected phone country. |
||
41 | * |
||
42 | * @var string |
||
43 | */ |
||
44 | protected $country; |
||
45 | |||
46 | /** |
||
47 | * Whether to allow lenient checks (i.e. landline numbers without area codes). |
||
48 | * |
||
49 | * @var bool |
||
50 | */ |
||
51 | protected $lenient = false; |
||
52 | |||
53 | /** |
||
54 | * @var \libphonenumber\PhoneNumberUtil |
||
55 | */ |
||
56 | protected $lib; |
||
57 | |||
58 | /** |
||
59 | * Phone constructor. |
||
60 | * |
||
61 | * @param string $number |
||
62 | */ |
||
63 | 105 | public function __construct($number) |
|
68 | |||
69 | /** |
||
70 | * Create a phone instance. |
||
71 | * |
||
72 | * @param string $number |
||
73 | * @param string|array $country |
||
74 | * @return static |
||
75 | */ |
||
76 | 27 | public static function make($number, $country = []) |
|
82 | |||
83 | /** |
||
84 | * Set the country to which the phone number belongs to. |
||
85 | * |
||
86 | * @param string|array $country |
||
87 | * @return static |
||
88 | */ |
||
89 | 90 | public function ofCountry($country) |
|
90 | { |
||
91 | 90 | $countries = is_array($country) ? $country : func_get_args(); |
|
92 | |||
93 | 90 | $instance = clone $this; |
|
94 | 90 | $instance->countries = array_unique( |
|
95 | 90 | array_merge($instance->countries, static::parseCountries($countries)) |
|
96 | 30 | ); |
|
97 | |||
98 | 90 | return $instance; |
|
99 | } |
||
100 | |||
101 | /** |
||
102 | * Format the phone number in international format. |
||
103 | * |
||
104 | * @return string |
||
105 | */ |
||
106 | 3 | public function formatInternational() |
|
110 | |||
111 | /** |
||
112 | * Format the phone number in national format. |
||
113 | * |
||
114 | * @return string |
||
115 | */ |
||
116 | 3 | public function formatNational() |
|
120 | |||
121 | /** |
||
122 | * Format the phone number in E164 format. |
||
123 | * |
||
124 | * @return string |
||
125 | */ |
||
126 | 18 | public function formatE164() |
|
130 | |||
131 | /** |
||
132 | * Format the phone number in RFC3966 format. |
||
133 | * |
||
134 | * @return string |
||
135 | */ |
||
136 | 6 | public function formatRFC3966() |
|
140 | |||
141 | /** |
||
142 | * Format the phone number in a given format. |
||
143 | * |
||
144 | * @param string $format |
||
145 | * @return string |
||
146 | * @throws \Propaganistas\LaravelPhone\Exceptions\NumberFormatException |
||
147 | */ |
||
148 | 45 | public function format($format) |
|
161 | |||
162 | /** |
||
163 | * Format the phone number in a way that it can be dialled from the provided country. |
||
164 | * |
||
165 | * @param string $country |
||
166 | * @return string |
||
167 | * @throws \Propaganistas\LaravelPhone\Exceptions\CountryCodeException |
||
168 | */ |
||
169 | 6 | View Code Duplication | public function formatForCountry($country) |
180 | |||
181 | /** |
||
182 | * Format the phone number in a way that it can be dialled from the provided country using a cellphone. |
||
183 | * |
||
184 | * @param string $country |
||
185 | * @param bool $removeFormatting |
||
186 | * @return string |
||
187 | * @throws \Propaganistas\LaravelPhone\Exceptions\CountryCodeException |
||
188 | */ |
||
189 | 6 | View Code Duplication | public function formatForMobileDialingInCountry($country, $removeFormatting = false) |
201 | |||
202 | /** |
||
203 | * Get the phone number's country. |
||
204 | * |
||
205 | * @return string |
||
206 | */ |
||
207 | 84 | public function getCountry() |
|
215 | |||
216 | /** |
||
217 | * Check if the phone number is of (a) given country(ies). |
||
218 | * |
||
219 | * @param string|array $country |
||
220 | * @return bool |
||
221 | */ |
||
222 | 3 | public function isOfCountry($country) |
|
228 | |||
229 | /** |
||
230 | * Filter the provided countries to the one that is valid for the number. |
||
231 | * |
||
232 | * @param string|array $countries |
||
233 | * @return string |
||
234 | * @throws \Propaganistas\LaravelPhone\Exceptions\NumberParseException |
||
235 | */ |
||
236 | 84 | protected function filterValidCountry($countries) |
|
237 | { |
||
238 | 84 | $result = Collection::make($countries) |
|
239 | 84 | ->filter(function ($country) { |
|
240 | 78 | $instance = $this->lib->parse($this->number, $country); |
|
241 | |||
242 | 78 | return $this->lenient |
|
243 | 36 | ? $this->lib->isPossibleNumber($instance, $country) |
|
244 | 78 | : $this->lib->isValidNumberForRegion($instance, $country); |
|
245 | 84 | })->first(); |
|
246 | |||
247 | // If we got a new result, return it. |
||
248 | 84 | if ($result) { |
|
249 | 72 | return $result; |
|
250 | } |
||
251 | |||
252 | // Last resort: try to detect it from an international number. |
||
253 | 42 | if ($this->numberLooksInternational()) { |
|
254 | 24 | $instance = $this->lib->parse($this->number, null); |
|
255 | |||
256 | 24 | if ($this->lib->isValidNumber($instance)) { |
|
257 | 24 | return $this->lib->getRegionCodeForNumber($instance); |
|
258 | } |
||
259 | 1 | } |
|
260 | |||
261 | 24 | throw NumberParseException::countryRequired($this->number); |
|
262 | } |
||
263 | |||
264 | /** |
||
265 | * Get the phone number's type. |
||
266 | * |
||
267 | * @param bool $asConstant |
||
268 | * @return string|int|null |
||
269 | */ |
||
270 | 15 | public function getType($asConstant = false) |
|
282 | |||
283 | /** |
||
284 | * Check if the phone number is of (a) given type(s). |
||
285 | * |
||
286 | * @param string $type |
||
287 | * @return bool |
||
288 | */ |
||
289 | 12 | public function isOfType($type) |
|
295 | |||
296 | /** |
||
297 | * Get the PhoneNumber instance of the current number. |
||
298 | * |
||
299 | * @return \libphonenumber\PhoneNumber |
||
300 | */ |
||
301 | 75 | public function getPhoneNumberInstance() |
|
305 | |||
306 | /** |
||
307 | * Determine whether the phone number seems to be in international format. |
||
308 | * |
||
309 | * @return bool |
||
310 | */ |
||
311 | 42 | protected function numberLooksInternational() |
|
315 | |||
316 | /** |
||
317 | * Enable lenient number parsing. |
||
318 | * |
||
319 | * @return $this |
||
320 | */ |
||
321 | 21 | public function lenient() |
|
327 | |||
328 | /** |
||
329 | * Convert the phone instance to JSON. |
||
330 | * |
||
331 | * @param int $options |
||
332 | * @return string |
||
333 | */ |
||
334 | 3 | public function toJson($options = 0) |
|
338 | |||
339 | /** |
||
340 | * Convert the phone instance into something JSON serializable. |
||
341 | * |
||
342 | * @return string |
||
343 | */ |
||
344 | 3 | public function jsonSerialize() |
|
348 | |||
349 | /** |
||
350 | * Convert the phone instance into a string representation. |
||
351 | * |
||
352 | * @return string |
||
353 | */ |
||
354 | 3 | public function serialize() |
|
358 | |||
359 | /** |
||
360 | * Reconstructs the phone instance from a string representation. |
||
361 | * |
||
362 | * @param string $serialized |
||
363 | */ |
||
364 | 3 | public function unserialize($serialized) |
|
370 | |||
371 | /** |
||
372 | * Convert the phone instance to a formatted number. |
||
373 | * |
||
374 | * @return string |
||
375 | */ |
||
376 | 9 | public function __toString() |
|
386 | } |