1<?php
2
3namespace libphonenumber;
4
5class PhoneNumber implements \Serializable
6{
7    /**
8     * The country calling code for this number, as defined by the International Telecommunication Union
9     * (ITU). For example, this would be 1 for NANPA countries, and 33 for France.
10     *
11     * @var int|null
12     */
13    protected $countryCode;
14    /**
15     * National (significant) Number is defined in International Telecommunication Union (ITU)
16     * Recommendation E.164. It is a language/country-neutral representation of a phone number at a
17     * country level. For countries which have the concept of an "area code" or "national destination
18     * code", this is included in the National (significant) Number. Although the ITU says the maximum
19     * length should be 15, we have found longer numbers in some countries e.g. Germany.
20     *
21     * Note that the National (significant) Number does not contain the National(trunk) prefix.
22     *
23     * @var string|null
24     */
25    protected $nationalNumber;
26    /**
27     * Extension is not standardized in ITU recommendations, except for being defined as a series of
28     * numbers with a maximum length of 40 digits. It is defined as a string here to accommodate for the
29     * possible use of a leading zero in the extension (organizations have complete freedom to do so,
30     * as there is no standard defined). However, only ASCII digits should be stored here.
31     *
32     * @var string|null
33     */
34    protected $extension;
35    /**
36     * In some countries, the national (significant) number starts with one or more "0"s without this
37     * being a national prefix or trunk code of some kind. For example, the leading zero in the national
38     * (significant) number of an Italian phone number indicates the number is a fixed-line number.
39     * There have been plans to migrate fixed-line numbers to start with the digit two since December
40     * 2000, but it has not happened yet. See http://en.wikipedia.org/wiki/%2B39 for more details.
41     *
42     * These fields can be safely ignored (there is no need to set them) for most countries. Some
43     * limited number of countries behave like Italy - for these cases, if the leading zero(s) of a
44     * number would be retained even when dialling internationally, set this flag to true, and also
45     * set the number of leading zeros.
46     *
47     * Clients who use the parsing functionality of the i18n phone number libraries
48     * will have these fields set if necessary automatically.
49     *
50     * @var bool|null
51     */
52    protected $italianLeadingZero;
53    /**
54     * This field is used to store the raw input string containing phone numbers before it was
55     * canonicalized by the library. For example, it could be used to store alphanumerical numbers
56     * such as "1-800-GOOG-411".
57     *
58     * @var string|null
59     */
60    protected $rawInput;
61    /**
62     * The source from which the country_code is derived. This is not set in the general parsing method,
63     * but in the method that parses and keeps raw_input. New fields could be added upon request.
64     *
65     * @see CountryCodeSource
66     *
67     * This must be one of the CountryCodeSource constants.
68     *
69     * @var int|null
70     */
71    protected $countryCodeSource = CountryCodeSource::UNSPECIFIED;
72    /**
73     * The carrier selection code that is preferred when calling this phone number domestically. This
74     * also includes codes that need to be dialed in some countries when calling from landlines to
75     * mobiles or vice versa. For example, in Columbia, a "3" needs to be dialed before the phone number
76     * itself when calling from a mobile phone to a domestic landline phone and vice versa.
77     *
78     * Note this is the "preferred" code, which means other codes may work as well.
79     *
80     * @var string|null
81     */
82    protected $preferredDomesticCarrierCode;
83    /**
84     * Whether this phone number has a number of leading zeros set.
85     *
86     * @var bool
87     */
88    protected $hasNumberOfLeadingZeros = false;
89    /**
90     * The number of leading zeros of this phone number.
91     *
92     * @var int
93     */
94    protected $numberOfLeadingZeros = 1;
95
96    /**
97     * Clears this phone number.
98     *
99     * This effectively resets this phone number to the state of a new instance.
100     *
101     * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
102     */
103    public function clear()
104    {
105        $this->clearCountryCode();
106        $this->clearNationalNumber();
107        $this->clearExtension();
108        $this->clearItalianLeadingZero();
109        $this->clearNumberOfLeadingZeros();
110        $this->clearRawInput();
111        $this->clearCountryCodeSource();
112        $this->clearPreferredDomesticCarrierCode();
113        return $this;
114    }
115
116    /**
117     * Clears the country code of this phone number.
118     *
119     * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
120     */
121    public function clearCountryCode()
122    {
123        $this->countryCode = null;
124        return $this;
125    }
126
127    /**
128     * Clears the national number of this phone number.
129     *
130     * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
131     */
132    public function clearNationalNumber()
133    {
134        $this->nationalNumber = null;
135        return $this;
136    }
137
138    /**
139     * Clears the extension of this phone number.
140     *
141     * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
142     */
143    public function clearExtension()
144    {
145        $this->extension = null;
146        return $this;
147    }
148
149    /**
150     * Clears the italian leading zero information of this phone number.
151     *
152     * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
153     */
154    public function clearItalianLeadingZero()
155    {
156        $this->italianLeadingZero = null;
157        return $this;
158    }
159
160    /**
161     * Clears the number of leading zeros of this phone number.
162     *
163     * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
164     */
165    public function clearNumberOfLeadingZeros()
166    {
167        $this->hasNumberOfLeadingZeros = false;
168        $this->numberOfLeadingZeros = 1;
169        return $this;
170    }
171
172    /**
173     * Clears the raw input of this phone number.
174     *
175     * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
176     */
177    public function clearRawInput()
178    {
179        $this->rawInput = null;
180        return $this;
181    }
182
183    /**
184     * Clears the country code source of this phone number.
185     *
186     * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
187     */
188    public function clearCountryCodeSource()
189    {
190        $this->countryCodeSource = CountryCodeSource::UNSPECIFIED;
191        return $this;
192    }
193
194    /**
195     * Clears the preferred domestic carrier code of this phone number.
196     *
197     * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
198     */
199    public function clearPreferredDomesticCarrierCode()
200    {
201        $this->preferredDomesticCarrierCode = null;
202        return $this;
203    }
204
205    /**
206     * Merges the information from another phone number into this phone number.
207     *
208     * @param PhoneNumber $other The phone number to copy.
209     *
210     * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
211     */
212    public function mergeFrom(PhoneNumber $other)
213    {
214        if ($other->hasCountryCode()) {
215            $this->setCountryCode($other->getCountryCode());
216        }
217        if ($other->hasNationalNumber()) {
218            $this->setNationalNumber($other->getNationalNumber());
219        }
220        if ($other->hasExtension()) {
221            $this->setExtension($other->getExtension());
222        }
223        if ($other->hasItalianLeadingZero()) {
224            $this->setItalianLeadingZero($other->isItalianLeadingZero());
225        }
226        if ($other->hasNumberOfLeadingZeros()) {
227            $this->setNumberOfLeadingZeros($other->getNumberOfLeadingZeros());
228        }
229        if ($other->hasRawInput()) {
230            $this->setRawInput($other->getRawInput());
231        }
232        if ($other->hasCountryCodeSource()) {
233            $this->setCountryCodeSource($other->getCountryCodeSource());
234        }
235        if ($other->hasPreferredDomesticCarrierCode()) {
236            $this->setPreferredDomesticCarrierCode($other->getPreferredDomesticCarrierCode());
237        }
238        return $this;
239    }
240
241    /**
242     * Returns whether this phone number has a country code set.
243     *
244     * @return bool True if a country code is set, false otherwise.
245     */
246    public function hasCountryCode()
247    {
248        return $this->countryCode !== null;
249    }
250
251    /**
252     * Returns the country code of this phone number.
253     *
254     * @return int|null The country code, or null if not set.
255     */
256    public function getCountryCode()
257    {
258        return $this->countryCode;
259    }
260
261    /**
262     * Sets the country code of this phone number.
263     *
264     * @param int $value The country code.
265     *
266     * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
267     */
268    public function setCountryCode($value)
269    {
270        $this->countryCode = (int) $value;
271        return $this;
272    }
273
274    /**
275     * Returns whether this phone number has a national number set.
276     *
277     * @return bool True if a national number is set, false otherwise.
278     */
279    public function hasNationalNumber()
280    {
281        return $this->nationalNumber !== null;
282    }
283
284    /**
285     * Returns the national number of this phone number.
286     *
287     * @return string|null The national number, or null if not set.
288     */
289    public function getNationalNumber()
290    {
291        return $this->nationalNumber;
292    }
293
294    /**
295     * Sets the national number of this phone number.
296     *
297     * @param string $value The national number.
298     *
299     * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
300     */
301    public function setNationalNumber($value)
302    {
303        $this->nationalNumber = (string) $value;
304        return $this;
305    }
306
307    /**
308     * Returns whether this phone number has an extension set.
309     *
310     * @return bool True if an extension is set, false otherwise.
311     */
312    public function hasExtension()
313    {
314        return $this->extension !== null;
315    }
316
317    /**
318     * Returns the extension of this phone number.
319     *
320     * @return string|null The extension, or null if not set.
321     */
322    public function getExtension()
323    {
324        return $this->extension;
325    }
326
327    /**
328     * Sets the extension of this phone number.
329     *
330     * @param string $value The extension.
331     *
332     * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
333     */
334    public function setExtension($value)
335    {
336        $this->extension = (string) $value;
337        return $this;
338    }
339
340    /**
341     * Returns whether this phone number has the italian leading zero information set.
342     *
343     * @return bool
344     */
345    public function hasItalianLeadingZero()
346    {
347        return $this->italianLeadingZero !== null;
348    }
349
350    /**
351     * Sets whether this phone number uses an italian leading zero.
352     *
353     * @param bool $value True to use italian leading zero, false otherwise.
354     *
355     * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
356     */
357    public function setItalianLeadingZero($value)
358    {
359        $this->italianLeadingZero = (bool) $value;
360        return $this;
361    }
362
363    /**
364     * Returns whether this phone number uses an italian leading zero.
365     *
366     * @return bool|null True if it uses an italian leading zero, false it it does not, null if not set.
367     */
368    public function isItalianLeadingZero()
369    {
370        return $this->italianLeadingZero;
371    }
372
373    /**
374     * Returns whether this phone number has a number of leading zeros set.
375     *
376     * @return bool True if a number of leading zeros is set, false otherwise.
377     */
378    public function hasNumberOfLeadingZeros()
379    {
380        return $this->hasNumberOfLeadingZeros;
381    }
382
383    /**
384     * Returns the number of leading zeros of this phone number.
385     *
386     * @return int The number of leading zeros.
387     */
388    public function getNumberOfLeadingZeros()
389    {
390        return $this->numberOfLeadingZeros;
391    }
392
393    /**
394     * Sets the number of leading zeros of this phone number.
395     *
396     * @param int $value The number of leading zeros.
397     *
398     * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
399     */
400    public function setNumberOfLeadingZeros($value)
401    {
402        $this->hasNumberOfLeadingZeros = true;
403        $this->numberOfLeadingZeros = (int) $value;
404        return $this;
405    }
406
407    /**
408     * Returns whether this phone number has a raw input.
409     *
410     * @return bool True if a raw input is set, false otherwise.
411     */
412    public function hasRawInput()
413    {
414        return $this->rawInput !== null;
415    }
416
417    /**
418     * Returns the raw input of this phone number.
419     *
420     * @return string|null The raw input, or null if not set.
421     */
422    public function getRawInput()
423    {
424        return $this->rawInput;
425    }
426
427    /**
428     * Sets the raw input of this phone number.
429     *
430     * @param string $value The raw input.
431     *
432     * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
433     */
434    public function setRawInput($value)
435    {
436        $this->rawInput = (string) $value;
437        return $this;
438    }
439
440    /**
441     * Returns whether this phone number has a country code source.
442     *
443     * @return bool True if a country code source is set, false otherwise.
444     */
445    public function hasCountryCodeSource()
446    {
447        return $this->countryCodeSource !== CountryCodeSource::UNSPECIFIED;
448    }
449
450    /**
451     * Returns the country code source of this phone number.
452     *
453     * @return int|null A CountryCodeSource constant, or null if not set.
454     */
455    public function getCountryCodeSource()
456    {
457        return $this->countryCodeSource;
458    }
459
460    /**
461     * Sets the country code source of this phone number.
462     *
463     * @param int $value A CountryCodeSource constant.
464     *
465     * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
466     */
467    public function setCountryCodeSource($value)
468    {
469        $this->countryCodeSource = (int) $value;
470        return $this;
471    }
472
473    /**
474     * Returns whether this phone number has a preferred domestic carrier code.
475     *
476     * @return bool True if a preferred domestic carrier code is set, false otherwise.
477     */
478    public function hasPreferredDomesticCarrierCode()
479    {
480        return $this->preferredDomesticCarrierCode !== null;
481    }
482
483    /**
484     * Returns the preferred domestic carrier code of this phone number.
485     *
486     * @return string|null The preferred domestic carrier code, or null if not set.
487     */
488    public function getPreferredDomesticCarrierCode()
489    {
490        return $this->preferredDomesticCarrierCode;
491    }
492
493    /**
494     * Sets the preferred domestic carrier code of this phone number.
495     *
496     * @param string $value The preferred domestic carrier code.
497     *
498     * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
499     */
500    public function setPreferredDomesticCarrierCode($value)
501    {
502        $this->preferredDomesticCarrierCode = (string) $value;
503        return $this;
504    }
505
506    /**
507     * Returns whether this phone number is equal to another.
508     *
509     * @param PhoneNumber $other The phone number to compare.
510     *
511     * @return bool True if the phone numbers are equal, false otherwise.
512     */
513    public function equals(PhoneNumber $other)
514    {
515        $sameType = get_class($other) == get_class($this);
516        $sameCountry = $this->hasCountryCode() == $other->hasCountryCode() &&
517            (!$this->hasCountryCode() || $this->getCountryCode() == $other->getCountryCode());
518        $sameNational = $this->hasNationalNumber() == $other->hasNationalNumber() &&
519            (!$this->hasNationalNumber() || $this->getNationalNumber() == $other->getNationalNumber());
520        $sameExt = $this->hasExtension() == $other->hasExtension() &&
521            (!$this->hasExtension() || $this->getExtension() == $other->getExtension());
522        $sameLead = $this->hasItalianLeadingZero() == $other->hasItalianLeadingZero() &&
523            (!$this->hasItalianLeadingZero() || $this->isItalianLeadingZero() == $other->isItalianLeadingZero());
524        $sameZeros = $this->getNumberOfLeadingZeros() == $other->getNumberOfLeadingZeros();
525        $sameRaw = $this->hasRawInput() == $other->hasRawInput() &&
526            (!$this->hasRawInput() || $this->getRawInput() == $other->getRawInput());
527        $sameCountrySource = $this->hasCountryCodeSource() == $other->hasCountryCodeSource() &&
528            (!$this->hasCountryCodeSource() || $this->getCountryCodeSource() == $other->getCountryCodeSource());
529        $samePrefCar = $this->hasPreferredDomesticCarrierCode() == $other->hasPreferredDomesticCarrierCode() &&
530            (!$this->hasPreferredDomesticCarrierCode() || $this->getPreferredDomesticCarrierCode(
531                ) == $other->getPreferredDomesticCarrierCode());
532        return $sameType && $sameCountry && $sameNational && $sameExt && $sameLead && $sameZeros && $sameRaw && $sameCountrySource && $samePrefCar;
533    }
534
535    /**
536     * Returns a string representation of this phone number.
537     * @return string
538     */
539    public function __toString()
540    {
541        $outputString = '';
542
543        $outputString .= 'Country Code: ' . $this->countryCode;
544        $outputString .= ' National Number: ' . $this->nationalNumber;
545        if ($this->hasItalianLeadingZero()) {
546            $outputString .= ' Leading Zero(s): true';
547        }
548        if ($this->hasNumberOfLeadingZeros()) {
549            $outputString .= ' Number of leading zeros: ' . $this->numberOfLeadingZeros;
550        }
551        if ($this->hasExtension()) {
552            $outputString .= ' Extension: ' . $this->extension;
553        }
554        if ($this->hasCountryCodeSource()) {
555            $outputString .= ' Country Code Source: ' . $this->countryCodeSource;
556        }
557        if ($this->hasPreferredDomesticCarrierCode()) {
558            $outputString .= ' Preferred Domestic Carrier Code: ' . $this->preferredDomesticCarrierCode;
559        }
560        return $outputString;
561    }
562
563    /**
564     * @inheritDoc
565     */
566    public function serialize()
567    {
568        return serialize(
569            array(
570                $this->countryCode,
571                $this->nationalNumber,
572                $this->extension,
573                $this->italianLeadingZero,
574                $this->numberOfLeadingZeros,
575                $this->rawInput,
576                $this->countryCodeSource,
577                $this->preferredDomesticCarrierCode
578            )
579        );
580    }
581
582    /**
583     * @inheritDoc
584     */
585    public function unserialize($serialized)
586    {
587        $data = unserialize($serialized);
588
589        list(
590            $this->countryCode,
591            $this->nationalNumber,
592            $this->extension,
593            $this->italianLeadingZero,
594            $this->numberOfLeadingZeros,
595            $this->rawInput,
596            $this->countryCodeSource,
597            $this->preferredDomesticCarrierCode
598        ) = $data;
599
600        if ($this->numberOfLeadingZeros > 1) {
601            $this->hasNumberOfLeadingZeros = true;
602        }
603    }
604}
605