1
|
|
|
<?php namespace Propaganistas\LaravelPhone; |
2
|
|
|
|
3
|
|
|
use Illuminate\Contracts\Support\Jsonable; |
4
|
|
|
use Illuminate\Support\Arr; |
5
|
|
|
use Illuminate\Support\Str; |
6
|
|
|
use JsonSerializable; |
7
|
|
|
use libphonenumber\NumberParseException; |
8
|
|
|
use libphonenumber\PhoneNumberFormat; |
9
|
|
|
use libphonenumber\PhoneNumberUtil; |
10
|
|
|
use Propaganistas\LaravelPhone\Exceptions\PhoneCountryException; |
11
|
|
|
use Propaganistas\LaravelPhone\Exceptions\PhoneFormatException; |
12
|
|
|
use Propaganistas\LaravelPhone\Traits\ParsesCountries; |
13
|
|
|
use Propaganistas\LaravelPhone\Traits\ParsesFormats; |
14
|
|
|
use Propaganistas\LaravelPhone\Traits\ParsesTypes; |
15
|
|
|
use Serializable; |
16
|
|
|
|
17
|
|
|
class Phone implements Jsonable, JsonSerializable, Serializable |
18
|
|
|
{ |
19
|
|
|
use ParsesCountries, |
20
|
|
|
ParsesFormats, |
21
|
|
|
ParsesTypes; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* The provided phone number. |
25
|
|
|
* |
26
|
|
|
* @var string |
27
|
|
|
*/ |
28
|
|
|
protected $number; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* The provided phone countries. |
32
|
|
|
* |
33
|
|
|
* @var array |
34
|
|
|
*/ |
35
|
|
|
protected $countries = []; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @var \libphonenumber\PhoneNumberUtil |
39
|
|
|
*/ |
40
|
|
|
protected $lib; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Phone constructor. |
44
|
|
|
* |
45
|
|
|
* @param string $number |
46
|
|
|
*/ |
47
|
|
|
public function __construct($number) |
48
|
|
|
{ |
49
|
|
|
$this->number = $number; |
50
|
|
|
$this->lib = PhoneNumberUtil::getInstance(); |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Create a phone instance. |
55
|
|
|
* |
56
|
|
|
* @param string $number |
57
|
|
|
* @param string|array $country |
58
|
|
|
* @return static |
59
|
|
|
*/ |
60
|
|
|
public static function make($number, $country = null) |
61
|
|
|
{ |
62
|
|
|
$instance = new static($number); |
63
|
|
|
|
64
|
|
|
return $instance->ofCountry($country); |
|
|
|
|
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* Set the country to which the phone number belongs to. |
69
|
|
|
* |
70
|
|
|
* @param string|array $country |
71
|
|
|
* @return $this |
72
|
|
|
*/ |
73
|
|
|
public function ofCountry($country) |
74
|
|
|
{ |
75
|
|
|
$instance = clone $this; |
76
|
|
|
$instance->countries = $instance->parseCountries($country); |
77
|
|
|
|
78
|
|
|
return $instance; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* Format the phone number in international format. |
83
|
|
|
* |
84
|
|
|
* @return string |
85
|
|
|
*/ |
86
|
|
|
public function formatInternational() |
87
|
|
|
{ |
88
|
|
|
return $this->format(PhoneNumberFormat::INTERNATIONAL); |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* Format the phone number in national format. |
93
|
|
|
* |
94
|
|
|
* @return string |
95
|
|
|
*/ |
96
|
|
|
public function formatNational() |
97
|
|
|
{ |
98
|
|
|
return $this->format(PhoneNumberFormat::NATIONAL); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* Format the phone number in E164 format. |
103
|
|
|
* |
104
|
|
|
* @return string |
105
|
|
|
*/ |
106
|
|
|
public function formatE164() |
107
|
|
|
{ |
108
|
|
|
return $this->format(PhoneNumberFormat::E164); |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* Format the phone number in RFC3966 format. |
113
|
|
|
* |
114
|
|
|
* @return string |
115
|
|
|
*/ |
116
|
|
|
public function formatRFC3966() |
117
|
|
|
{ |
118
|
|
|
return $this->format(PhoneNumberFormat::RFC3966); |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
/** |
122
|
|
|
* Format the phone number in a given format. |
123
|
|
|
* |
124
|
|
|
* @param string $format |
125
|
|
|
* @return string |
126
|
|
|
*/ |
127
|
|
|
public function format($format) |
128
|
|
|
{ |
129
|
|
|
if (! ($format = static::parseFormat($format))) { |
130
|
|
|
return $this->throwFormatException('Unknown format "' . (string) $format . '"'); |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
$country = Arr::get($this->countries, 0); |
134
|
|
|
|
135
|
|
|
if (! $country && ! Str::startsWith($this->number, '+')) { |
136
|
|
|
return $this->throwFormatException('A country should be provided or the number should be in international format'); |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
return $this->lib->format( |
140
|
|
|
$this->getPhoneNumberInstance(), |
141
|
|
|
$format |
142
|
|
|
); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* Format the phone number in a way that it can be dialled from the provided country. |
147
|
|
|
* |
148
|
|
|
* @param string $country |
149
|
|
|
* @return string |
150
|
|
|
*/ |
151
|
|
View Code Duplication |
public function formatForCountry($country) |
|
|
|
|
152
|
|
|
{ |
153
|
|
|
if (! static::isCountryCode($country)) { |
154
|
|
|
return $this->throwCountryException($country); |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
return $this->lib->formatOutOfCountryCallingNumber( |
158
|
|
|
$this->getPhoneNumberInstance(), |
159
|
|
|
$country |
160
|
|
|
); |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* Format the phone number in a way that it can be dialled from the provided country using a cellphone. |
165
|
|
|
* |
166
|
|
|
* @param string $country |
167
|
|
|
* @param bool $removeFormatting |
168
|
|
|
* @return string |
169
|
|
|
*/ |
170
|
|
View Code Duplication |
public function formatForMobileDialingInCountry($country, $removeFormatting = false) |
|
|
|
|
171
|
|
|
{ |
172
|
|
|
if (! static::isCountryCode($country)) { |
173
|
|
|
return $this->throwCountryException($country); |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
return $this->lib->formatNumberForMobileDialing( |
177
|
|
|
$this->getPhoneNumberInstance(), |
178
|
|
|
$country, |
179
|
|
|
$removeFormatting |
180
|
|
|
); |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* Get the phone number's country. |
185
|
|
|
* |
186
|
|
|
* @return string |
187
|
|
|
*/ |
188
|
|
|
public function getCountry() |
189
|
|
|
{ |
190
|
|
|
return $this->lib->getRegionCodeForNumber($this->getPhoneNumberInstance()); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* Get the phone number's type. |
195
|
|
|
* |
196
|
|
|
* @param bool $asConstant |
197
|
|
|
* @return string|int |
198
|
|
|
*/ |
199
|
|
|
public function getType($asConstant = false) |
200
|
|
|
{ |
201
|
|
|
$type = $this->lib->getNumberType($this->getPhoneNumberInstance()); |
202
|
|
|
|
203
|
|
|
return $asConstant ? $type : array_search($type, static::$types); |
|
|
|
|
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
/** |
207
|
|
|
* Get the PhoneNumber instance of the current number. |
208
|
|
|
* |
209
|
|
|
* @return \libphonenumber\PhoneNumber |
210
|
|
|
*/ |
211
|
|
|
public function getPhoneNumberInstance() |
212
|
|
|
{ |
213
|
|
|
// Let's try each provided country. |
214
|
|
|
foreach ($this->countries as $country) { |
215
|
|
|
try { |
216
|
|
|
return $this->lib->parse($this->number, $country); |
217
|
|
|
} catch (NumberParseException $exception) { |
|
|
|
|
218
|
|
|
} |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
// Otherwise let's try to autodetect the country if the number is in international format. |
222
|
|
|
if (Str::startsWith($this->number, '+')) { |
223
|
|
|
try { |
224
|
|
|
return $this->lib->parse($this->number, null); |
225
|
|
|
} catch (NumberParseException $exception) { |
|
|
|
|
226
|
|
|
} |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
return $this->throwCountryException($this->number); |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* Throw a IndeterminablePhoneCountryException. |
234
|
|
|
* |
235
|
|
|
* @param $message |
236
|
|
|
* @throws \Propaganistas\LaravelPhone\Exceptions\PhoneCountryException |
237
|
|
|
*/ |
238
|
|
|
protected function throwCountryException($message) |
239
|
|
|
{ |
240
|
|
|
throw new PhoneCountryException($message); |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
/** |
244
|
|
|
* Throw a PhoneFormatException. |
245
|
|
|
* |
246
|
|
|
* @param string $message |
247
|
|
|
* @throws \Propaganistas\LaravelPhone\Exceptions\PhoneFormatException |
248
|
|
|
*/ |
249
|
|
|
protected function throwFormatException($message) |
250
|
|
|
{ |
251
|
|
|
throw new PhoneFormatException($message); |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
/** |
255
|
|
|
* Convert the phone instance to JSON. |
256
|
|
|
* |
257
|
|
|
* @param int $options |
258
|
|
|
* @return string |
259
|
|
|
*/ |
260
|
|
|
public function toJson($options = 0) |
261
|
|
|
{ |
262
|
|
|
return json_encode($this->jsonSerialize(), $options); |
263
|
|
|
} |
264
|
|
|
|
265
|
|
|
/** |
266
|
|
|
* Convert the phone instance into something JSON serializable. |
267
|
|
|
* |
268
|
|
|
* @return string |
269
|
|
|
*/ |
270
|
|
|
public function jsonSerialize() |
271
|
|
|
{ |
272
|
|
|
return $this->formatE164(); |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* Convert the phone instance into a string representation. |
277
|
|
|
* |
278
|
|
|
* @return string |
279
|
|
|
*/ |
280
|
|
|
public function serialize() |
281
|
|
|
{ |
282
|
|
|
return $this->formatE164(); |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
/** |
286
|
|
|
* Reconstructs the phone instance from a string representation. |
287
|
|
|
* |
288
|
|
|
* @param string $serialized |
289
|
|
|
*/ |
290
|
|
|
public function unserialize($serialized) |
291
|
|
|
{ |
292
|
|
|
$this->number = $serialized; |
293
|
|
|
$this->countries = []; |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
/** |
297
|
|
|
* Convert the phone instance to a formatted number. |
298
|
|
|
* |
299
|
|
|
* @return string |
300
|
|
|
*/ |
301
|
|
|
public function __toString() |
302
|
|
|
{ |
303
|
|
|
return $this->formatE164(); |
304
|
|
|
} |
305
|
|
|
} |
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.