Exemplo n.º 1
0
 /**
  * Takes two phone numbers and compares them for equality.
  *
  * <p>Returns EXACT_MATCH if the country_code, NSN, presence of a leading zero
  * for Italian numbers and any extension present are the same. Returns NSN_MATCH
  * if either or both has no region specified, and the NSNs and extensions are
  * the same. Returns SHORT_NSN_MATCH if either or both has no region specified,
  * or the region specified is the same, and one NSN could be a shorter version
  * of the other number. This includes the case where one has an extension
  * specified, and the other does not. Returns NO_MATCH otherwise. For example,
  * the numbers +1 345 657 1234 and 657 1234 are a SHORT_NSN_MATCH. The numbers
  * +1 345 657 1234 and 345 657 are a NO_MATCH.
  *
  * @param $firstNumberIn PhoneNumber|string First number to compare. If it is a
  * string it can contain formatting, and can have country calling code specified
  * with + at the start.
  * @param $secondNumberIn PhoneNumber|string Second number to compare. If it is a
  * string it can contain formatting, and can have country calling code specified
  * with + at the start.
  * @throws \InvalidArgumentException
  * @return int {MatchType} NOT_A_NUMBER, NO_MATCH,
  */
 public function isNumberMatch($firstNumberIn, $secondNumberIn)
 {
     if (is_string($firstNumberIn) && is_string($secondNumberIn)) {
         try {
             $firstNumberAsProto = $this->parse($firstNumberIn, self::UNKNOWN_REGION);
             return $this->isNumberMatch($firstNumberAsProto, $secondNumberIn);
         } catch (NumberParseException $e) {
             if ($e->getErrorType() === NumberParseException::INVALID_COUNTRY_CODE) {
                 try {
                     $secondNumberAsProto = $this->parse($secondNumberIn, self::UNKNOWN_REGION);
                     return $this->isNumberMatch($secondNumberAsProto, $firstNumberIn);
                 } catch (NumberParseException $e2) {
                     if ($e2->getErrorType() === NumberParseException::INVALID_COUNTRY_CODE) {
                         try {
                             $firstNumberProto = new PhoneNumber();
                             $secondNumberProto = new PhoneNumber();
                             $this->parseHelper($firstNumberIn, null, false, false, $firstNumberProto);
                             $this->parseHelper($secondNumberIn, null, false, false, $secondNumberProto);
                             return $this->isNumberMatch($firstNumberProto, $secondNumberProto);
                         } catch (NumberParseException $e3) {
                             // Fall through and return MatchType::NOT_A_NUMBER
                         }
                     }
                 }
             }
         }
         return MatchType::NOT_A_NUMBER;
     }
     if ($firstNumberIn instanceof PhoneNumber && is_string($secondNumberIn)) {
         // First see if the second number has an implicit country calling code, by attempting to parse
         // it.
         try {
             $secondNumberAsProto = $this->parse($secondNumberIn, self::UNKNOWN_REGION);
             return $this->isNumberMatch($firstNumberIn, $secondNumberAsProto);
         } catch (NumberParseException $e) {
             if ($e->getErrorType() === NumberParseException::INVALID_COUNTRY_CODE) {
                 // The second number has no country calling code. EXACT_MATCH is no longer possible.
                 // We parse it as if the region was the same as that for the first number, and if
                 // EXACT_MATCH is returned, we replace this with NSN_MATCH.
                 $firstNumberRegion = $this->getRegionCodeForCountryCode($firstNumberIn->getCountryCode());
                 try {
                     if ($firstNumberRegion != self::UNKNOWN_REGION) {
                         $secondNumberWithFirstNumberRegion = $this->parse($secondNumberIn, $firstNumberRegion);
                         $match = $this->isNumberMatch($firstNumberIn, $secondNumberWithFirstNumberRegion);
                         if ($match === MatchType::EXACT_MATCH) {
                             return MatchType::NSN_MATCH;
                         }
                         return $match;
                     } else {
                         // If the first number didn't have a valid country calling code, then we parse the
                         // second number without one as well.
                         $secondNumberProto = new PhoneNumber();
                         $this->parseHelper($secondNumberIn, null, false, false, $secondNumberProto);
                         return $this->isNumberMatch($firstNumberIn, $secondNumberProto);
                     }
                 } catch (NumberParseException $e2) {
                     // Fall-through to return NOT_A_NUMBER.
                 }
             }
         }
     }
     if ($firstNumberIn instanceof PhoneNumber && $secondNumberIn instanceof PhoneNumber) {
         // Make copies of the phone number so that the numbers passed in are not edited.
         $firstNumber = new PhoneNumber();
         $firstNumber->mergeFrom($firstNumberIn);
         $secondNumber = new PhoneNumber();
         $secondNumber->mergeFrom($secondNumberIn);
         // First clear raw_input, country_code_source and preferred_domestic_carrier_code fields and any
         // empty-string extensions so that we can use the proto-buffer equality method.
         $firstNumber->clearRawInput();
         $firstNumber->clearCountryCodeSource();
         $firstNumber->clearPreferredDomesticCarrierCode();
         $secondNumber->clearRawInput();
         $secondNumber->clearCountryCodeSource();
         $secondNumber->clearPreferredDomesticCarrierCode();
         if ($firstNumber->hasExtension() && mb_strlen($firstNumber->getExtension()) === 0) {
             $firstNumber->clearExtension();
         }
         if ($secondNumber->hasExtension() && mb_strlen($secondNumber->getExtension()) === 0) {
             $secondNumber->clearExtension();
         }
         // Early exit if both had extensions and these are different.
         if ($firstNumber->hasExtension() && $secondNumber->hasExtension() && $firstNumber->getExtension() != $secondNumber->getExtension()) {
             return MatchType::NO_MATCH;
         }
         $firstNumberCountryCode = $firstNumber->getCountryCode();
         $secondNumberCountryCode = $secondNumber->getCountryCode();
         // Both had country_code specified.
         if ($firstNumberCountryCode != 0 && $secondNumberCountryCode != 0) {
             if ($firstNumber->equals($secondNumber)) {
                 return MatchType::EXACT_MATCH;
             } elseif ($firstNumberCountryCode == $secondNumberCountryCode && $this->isNationalNumberSuffixOfTheOther($firstNumber, $secondNumber)) {
                 // A SHORT_NSN_MATCH occurs if there is a difference because of the presence or absence of
                 // an 'Italian leading zero', the presence or absence of an extension, or one NSN being a
                 // shorter variant of the other.
                 return MatchType::SHORT_NSN_MATCH;
             }
             // This is not a match.
             return MatchType::NO_MATCH;
         }
         // Checks cases where one or both country_code fields were not specified. To make equality
         // checks easier, we first set the country_code fields to be equal.
         $firstNumber->setCountryCode($secondNumberCountryCode);
         // If all else was the same, then this is an NSN_MATCH.
         if ($firstNumber->equals($secondNumber)) {
             return MatchType::NSN_MATCH;
         }
         if ($this->isNationalNumberSuffixOfTheOther($firstNumber, $secondNumber)) {
             return MatchType::SHORT_NSN_MATCH;
         }
         return MatchType::NO_MATCH;
     }
     return MatchType::NOT_A_NUMBER;
 }
 /**
  * Merges the information from another phone number into this phone number.
  *
  * @param PhoneNumber $other The phone number to copy.
  *
  * @return PhoneNumber This PhoneNumber instance, for chaining method calls.
  */
 public function mergeFrom(PhoneNumber $other)
 {
     if ($other->hasCountryCode()) {
         $this->setCountryCode($other->getCountryCode());
     }
     if ($other->hasNationalNumber()) {
         $this->setNationalNumber($other->getNationalNumber());
     }
     if ($other->hasExtension()) {
         $this->setExtension($other->getExtension());
     }
     if ($other->hasItalianLeadingZero()) {
         $this->setItalianLeadingZero($other->isItalianLeadingZero());
     }
     if ($other->hasNumberOfLeadingZeros()) {
         $this->setNumberOfLeadingZeros($other->getNumberOfLeadingZeros());
     }
     if ($other->hasRawInput()) {
         $this->setRawInput($other->getRawInput());
     }
     if ($other->hasCountryCodeSource()) {
         $this->setCountryCodeSource($other->getCountryCodeSource());
     }
     if ($other->hasPreferredDomesticCarrierCode()) {
         $this->setPreferredDomesticCarrierCode($other->getPreferredDomesticCarrierCode());
     }
     return $this;
 }
 /**
  * Gets the expected cost category of a short number (however, nothing is implied about its
  * validity). If the country calling code is unique to a region, this method behaves exactly the
  * same as {@link #getExpectedCostForRegion(String, String)}. However, if the country calling
  * code is shared by multiple regions, then it returns the highest cost in the sequence
  * PREMIUM_RATE, UNKNOWN_COST, STANDARD_RATE, TOLL_FREE. The reason for the position of
  * UNKNOWN_COST in this order is that if a number is UNKNOWN_COST in one region but STANDARD_RATE
  * or TOLL_FREE in another, its expected cost cannot be estimated as one of the latter since it
  * might be a PREMIUM_RATE number.
  *
  * For example, if a number is STANDARD_RATE in the US, but TOLL_FREE in Canada, the expected cost
  * returned by this method will be STANDARD_RATE, since the NANPA countries share the same country
  * calling code.
  *
  * Note: If the region from which the number is dialed is known, it is highly preferable to call
  * {@link #getExpectedCostForRegion(String, String)} instead.
  *
  * @param $number PhoneNumber the short number for which we want to know the expected cost category
  * @return int the highest expected cost category of the short number in the region(s) with the given
  *     country calling code
  */
 public function getExpectedCost(PhoneNumber $number)
 {
     $regionCodes = $this->phoneUtil->getRegionCodesForCountryCode($number->getCountryCode());
     if (count($regionCodes) == 0) {
         return ShortNumberCost::UNKNOWN_COST;
     }
     $shortNumber = $this->phoneUtil->getNationalSignificantNumber($number);
     if (count($regionCodes) == 1) {
         return $this->getExpectedCostForRegion($shortNumber, $regionCodes[0]);
     }
     $cost = ShortNumberCost::TOLL_FREE;
     foreach ($regionCodes as $regionCode) {
         $costForRegion = $this->getExpectedCostForRegion($shortNumber, $regionCode);
         switch ($costForRegion) {
             case ShortNumberCost::PREMIUM_RATE:
                 return ShortNumberCost::PREMIUM_RATE;
             case ShortNumberCost::UNKNOWN_COST:
                 $cost = ShortNumberCost::UNKNOWN_COST;
                 break;
             case ShortNumberCost::STANDARD_RATE:
                 if ($cost != ShortNumberCost::UNKNOWN_COST) {
                     $cost = ShortNumberCost::STANDARD_RATE;
                 }
                 break;
             case ShortNumberCost::TOLL_FREE:
                 // Do nothing
                 break;
         }
     }
     return $cost;
 }
 /**
  * Formats a phone number in national format for dialing using the carrier as specified in the
  * {@code carrierCode}. The {@code carrierCode} will always be used regardless of whether the
  * phone number already has a preferred domestic carrier code stored. If {@code carrierCode}
  * contains an empty string, returns the number in national format without any carrier code.
  *
  * @param PhoneNumber $number  the phone number to be formatted
  * @param String $carrierCode  the carrier selection code to be used
  * @return String the formatted phone number in national format for dialing using the carrier as
  *          specified in the {@code carrierCode}
  */
 public function formatNationalNumberWithCarrierCode(PhoneNumber $number, $carrierCode)
 {
     $countryCallingCode = $number->getCountryCode();
     $nationalSignificantNumber = $this->getNationalSignificantNumber($number);
     if (!$this->hasValidCountryCallingCode($countryCallingCode)) {
         return $nationalSignificantNumber;
     }
     // Note getRegionCodeForCountryCode() is used because formatting information for regions which
     // share a country calling code is contained by only one region for performance reasons. For
     // example, for NANPA regions it will be contained in the metadata for US.
     $regionCode = $this->getRegionCodeForCountryCode($countryCallingCode);
     // Metadata cannot be null because the country calling code is valid.
     $metadata = $this->getMetadataForRegionOrCallingCode($countryCallingCode, $regionCode);
     $formattedNumber = $this->formatNsn($nationalSignificantNumber, $metadata, PhoneNumberFormat::NATIONAL, $carrierCode);
     $this->maybeAppendFormattedExtension($number, $metadata, PhoneNumberFormat::NATIONAL, $formattedNumber);
     $this->prefixNumberWithCountryCallingCode($countryCallingCode, PhoneNumberFormat::NATIONAL, $formattedNumber);
     return $formattedNumber;
 }