Skip to content

Commit

Permalink
Remove backwards compatibility break from Phone rule
Browse files Browse the repository at this point in the history
In version 2.3, the Phone rule started to require
"giggly/libphonenumber-for-php" as a dependency. That was a backward
compatibility break, but the validation also became stricter, and phone
numbers without country codes would not be considered valid.

This commit will revert the backward compatibility break. That way, when
validating a phone number without a country code (the behaviour from
version 2.2), the Phone will not use an external library.

Signed-off-by: Henrique Moody <[email protected]>
  • Loading branch information
henriquemoody committed Mar 11, 2024
1 parent fb322df commit 788939e
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 22 deletions.
17 changes: 10 additions & 7 deletions docs/rules/Phone.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
# Phone

- `Phone()`
- `Phone(string $countyCode)`

Validates whether the input is a valid phone number. This rule requires
the `giggsey/libphonenumber-for-php-lite` package.

Validates whether the input is a valid phone number.

```php
v::phone()->validate('+1 650 253 00 00'); // true
v::phone('BR')->validate('+55 11 91111 1111'); // true
v::phone('BR')->validate('11 91111 1111'); // false
```

## Note

When validating with `$countryCode`, this rule will require the `giggsey/libphonenumber-for-php-lite` package.

## Categorization

- Strings

## Changelog

Version | Description
--------|-------------
2.3.0 | Updated to use external validator
0.5.0 | Created
| Version | Description |
|--------:|-------------------------------------|
| 2.3.0 | Introduced a validation per country |
| 0.5.0 | Created |

***
See also:
Expand Down
39 changes: 24 additions & 15 deletions library/Rules/Phone.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
use Respect\Validation\Exceptions\ComponentException;

use function class_exists;
use function is_null;
use function is_scalar;
use function preg_match;
use function sprintf;

/**
Expand All @@ -24,6 +24,9 @@
* Validates an international or country-specific telephone number
*
* @author Alexandre Gomes Gaigalas <[email protected]>
* @author Danilo Correa <[email protected]>
* @author Graham Campbell <[email protected]>
* @author Henrique Moody <[email protected]>
*/
final class Phone extends AbstractRule
{
Expand All @@ -32,42 +35,48 @@ final class Phone extends AbstractRule
*/
private $countryCode;

/**
* {@inheritDoc}
*/
public function __construct(?string $countryCode = null)
{
$this->countryCode = $countryCode;
if ($countryCode === null) {
return;
}

if (!is_null($countryCode) && !(new CountryCode())->validate($countryCode)) {
throw new ComponentException(
sprintf(
'Invalid country code %s',
$countryCode
)
);
if (!(new CountryCode())->validate($countryCode)) {
throw new ComponentException(sprintf('Invalid country code %s', $countryCode));
}

if (!class_exists(PhoneNumberUtil::class)) {
throw new ComponentException('The phone validator requires giggsey/libphonenumber-for-php');
}
}

/**
* {@inheritDoc}
*/
public function validate($input): bool
{
if (!is_scalar($input)) {
return false;
}

if ($this->countryCode === null) {
return preg_match($this->getPregFormat(), (string) $input) > 0;
}

try {
return PhoneNumberUtil::getInstance()->isValidNumber(
PhoneNumberUtil::getInstance()->parse((string) $input, $this->countryCode)
);
} catch (NumberParseException $e) {
} catch (NumberParseException) {
return false;
}
}

private function getPregFormat(): string
{
return sprintf(
'/^\+?(%1$s)? ?(?(?=\()(\(%2$s\) ?%3$s)|([. -]?(%2$s[. -]*)?%3$s))$/',
'\d{0,3}',
'\d{1,3}',
'((\d{3,5})[. -]?(\d{2}[. -]?\d{2})|(\d{2}[. -]?){4})'
);
}
}
75 changes: 75 additions & 0 deletions tests/unit/Rules/PhoneTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,52 @@ public static function providerForValidInput(): array
[new Phone(), '+7 (999) 999-99-99'],
[new Phone(), '+7(999)999-99-99'],
[new Phone(), '+7(999)999-9999'],
[new Phone(), '+5-555-555-5555'],
[new Phone(), '+5 555 555 5555'],
[new Phone(), '+5.555.555.5555'],
[new Phone(), '5-555-555-5555'],
[new Phone(), '5.555.555.5555'],
[new Phone(), '5 555 555 5555'],
[new Phone(), '555.555.5555'],
[new Phone(), '555 555 5555'],
[new Phone(), '555-555-5555'],
[new Phone(), '555-5555555'],
[new Phone(), '5(555)555.5555'],
[new Phone(), '+5(555)555.5555'],
[new Phone(), '+5(555)555 5555'],
[new Phone(), '+5(555)555-5555'],
[new Phone(), '+5(555)5555555'],
[new Phone(), '(555)5555555'],
[new Phone(), '(555)555.5555'],
[new Phone(), '(555)555-5555'],
[new Phone(), '(555) 555 5555'],
[new Phone(), '55555555555'],
[new Phone(), '5555555555'],
[new Phone(), '+33(1)2222222'],
[new Phone(), '+33(1)222 2222'],
[new Phone(), '+33(1)222.2222'],
[new Phone(), '+33(1)22 22 22 22'],
[new Phone(), '33(1)2222222'],
[new Phone(), '33(1)22222222'],
[new Phone(), '33(1)22 22 22 22'],
[new Phone(), '(020) 7476 4026'],
[new Phone(), '33(020) 7777 7777'],
[new Phone(), '33(020)7777 7777'],
[new Phone(), '+33(020) 7777 7777'],
[new Phone(), '+33(020)7777 7777'],
[new Phone(), '03-6106666'],
[new Phone(), '036106666'],
[new Phone(), '+33(11) 97777 7777'],
[new Phone(), '+3311977777777'],
[new Phone(), '11977777777'],
[new Phone(), '11 97777 7777'],
[new Phone(), '(11) 97777 7777'],
[new Phone(), '(11) 97777-7777'],
[new Phone(), '555-5555'],
[new Phone(), '5555555'],
[new Phone(), '555.5555'],
[new Phone(), '555 5555'],
[new Phone(), '+1 (555) 555 5555'],
[new Phone('BR'), '+55 11 91111 1111'],
[new Phone('BR'), '11 91111 1111'], // no international prefix
[new Phone('BR'), '+5511911111111'], // no whitespace
Expand All @@ -68,6 +114,35 @@ public static function providerForValidInput(): array
public static function providerForInvalidInput(): array
{
return [
[new Phone(), ''],
[new Phone(), '123'],
[new Phone(), '(11- 97777-7777'],
[new Phone(), '-11) 97777-7777'],
[new Phone(), 's555-5555'],
[new Phone(), '555-555'],
[new Phone(), '555555'],
[new Phone(), '555+5555'],
[new Phone(), '(555)555555'],
[new Phone(), '(555)55555'],
[new Phone(), '+(555)555 555'],
[new Phone(), '+5(555)555 555'],
[new Phone(), '+5(555)555 555 555'],
[new Phone(), '555)555 555'],
[new Phone(), '+5(555)5555 555'],
[new Phone(), '(555)55 555'],
[new Phone(), '(555)5555 555'],
[new Phone(), '+5(555)555555'],
[new Phone(), '5(555)55 55555'],
[new Phone(), '(5)555555'],
[new Phone(), '+55(5)55 5 55 55'],
[new Phone(), '+55(5)55 55 55 5'],
[new Phone(), '+55(5)55 55 55'],
[new Phone(), '+55(5)5555 555'],
[new Phone(), '+55()555 5555'],
[new Phone(), '03610666-5'],
[new Phone(), 'text'],
[new Phone(), "555\n5555"],
[new Phone(), []],
[new Phone(), '+1-650-253-00-0'],
[new Phone('BR'), '+1 11 91111 1111'], // invalid + code for BR
];
Expand Down

0 comments on commit 788939e

Please sign in to comment.