Skip to content

Commit

Permalink
Merge pull request #15 from thewilkybarkid/constraint-types
Browse files Browse the repository at this point in the history
Validate phone number type
  • Loading branch information
thewilkybarkid committed Oct 20, 2014
2 parents b8b71de + 0e6ba89 commit 59d7d53
Show file tree
Hide file tree
Showing 12 changed files with 214 additions and 10 deletions.
2 changes: 1 addition & 1 deletion Form/Type/PhoneNumberType.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
'compound' => false,
'default_region' => PhoneNumberUtil::UNKNOWN_REGION,
'format' => PhoneNumberFormat::INTERNATIONAL,
'invalid_message' => 'This is not a valid phone number.',
'invalid_message' => 'This value is not a valid phone number.',
)
);
}
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,10 @@ You can set the default region through the `defaultRegion` property:
* @AssertPhoneNumber(defaultRegion="GB")
*/
private $phoneNumber;

By default any valid phone number will be accepted. You can restrict the type through the `type` property, recognised values are `mobile` and `fixed_line`. (Note the libphonenumber cannot always distinguish between mobile and fixed-line numbers (eg in the USA), in which case it will be accepted.)

/**
* @AssertPhoneNumber(type="mobile")
*/
private $mobilePhoneNumber;
19 changes: 19 additions & 0 deletions Resources/translations/validators.en.xlf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="file.ext">
<body>
<trans-unit id="1">
<source>This value is not a valid phone number.</source>
<target>This value is not a valid phone number.</target>
</trans-unit>
<trans-unit id="2">
<source>This value is not a valid fixed-line number.</source>
<target>This value is not a valid fixed-line number.</target>
</trans-unit>
<trans-unit id="3">
<source>This value is not a valid mobile number.</source>
<target>This value is not a valid mobile number.</target>
</trans-unit>
</body>
</file>
</xliff>
11 changes: 11 additions & 0 deletions Resources/translations/validators.en_CA.xlf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="file.ext">
<body>
<trans-unit id="3">
<source>This value is not a valid mobile number.</source>
<target>This value is not a valid cell number.</target>
</trans-unit>
</body>
</file>
</xliff>
11 changes: 11 additions & 0 deletions Resources/translations/validators.en_PH.xlf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="file.ext">
<body>
<trans-unit id="3">
<source>This value is not a valid mobile number.</source>
<target>This value is not a valid handphone number.</target>
</trans-unit>
</body>
</file>
</xliff>
11 changes: 11 additions & 0 deletions Resources/translations/validators.en_SG.xlf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="file.ext">
<body>
<trans-unit id="3">
<source>This value is not a valid mobile number.</source>
<target>This value is not a valid handphone number.</target>
</trans-unit>
</body>
</file>
</xliff>
11 changes: 11 additions & 0 deletions Resources/translations/validators.en_US.xlf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="file.ext">
<body>
<trans-unit id="3">
<source>This value is not a valid mobile number.</source>
<target>This value is not a valid cell number.</target>
</trans-unit>
</body>
</file>
</xliff>
11 changes: 11 additions & 0 deletions Resources/translations/validators.en_ZA.xlf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="file.ext">
<body>
<trans-unit id="3">
<source>This value is not a valid mobile number.</source>
<target>This value is not a valid cell number.</target>
</trans-unit>
</body>
</file>
</xliff>
34 changes: 34 additions & 0 deletions Tests/Validator/Constraints/PhoneNumberTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,38 @@ public function testProperties()
$this->assertObjectHasAttribute('type', $phoneNumber);
$this->assertObjectHasAttribute('defaultRegion', $phoneNumber);
}

/**
* @dataProvider messageProvider
*/
public function testMessage($message = null, $type = null, $expectedMessage)
{
$phoneNumber = new PhoneNumber();

if (null !== $message) {
$phoneNumber->message = $message;
}
if (null !== $type) {
$phoneNumber->type = $type;
}

$this->assertSame($expectedMessage, $phoneNumber->getMessage());
}

/**
* 0 => Message (optional)
* 1 => Type (optional)
* 2 => Expected message
*/
public function messageProvider()
{
return array(
array(null, null, 'This value is not a valid phone number.'),
array(null, 'fixed_line', 'This value is not a valid fixed-line number.'),
array(null, 'mobile', 'This value is not a valid mobile number.'),
array('foo', null, 'foo'),
array('foo', 'fixed_line', 'foo'),
array('foo', 'mobile', 'foo'),
);
}
}
40 changes: 35 additions & 5 deletions Tests/Validator/Constraints/PhoneNumberValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

namespace Misd\PhoneNumberBundle\Tests\Validator\Constraints;

use libphonenumber\PhoneNumber as PhoneNumberObject;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberUtil;
use Misd\PhoneNumberBundle\Validator\Constraints\PhoneNumber;
use Misd\PhoneNumberBundle\Validator\Constraints\PhoneNumberValidator;
Expand All @@ -33,17 +35,32 @@ public function testInstanceOf()
/**
* @dataProvider validateProvider
*/
public function testValidate($value, $violates, $defaultRegion = PhoneNumberUtil::UNKNOWN_REGION)
public function testValidate($value, $violates, $type = null, $defaultRegion = null)
{
$validator = new PhoneNumberValidator();
$context = $this->getMock('Symfony\Component\Validator\ExecutionContextInterface');
$validator->initialize($context);

$constraint = new PhoneNumber();
$constraint->defaultRegion = $defaultRegion;
if (null !== $type) {
$constraint->type = $type;
}
if (null !== $defaultRegion) {
$constraint->defaultRegion = $defaultRegion;
}

if (true === $violates) {
$context->expects($this->once())->method('addViolation');
if ($value instanceof PhoneNumberObject) {
$constraintValue = PhoneNumberUtil::getInstance()->format($value, PhoneNumberFormat::INTERNATIONAL);
} else {
$constraintValue = (string) $value;
}

$context->expects($this->once())->method('addViolation')
->with(
$constraint->getMessage(),
array('{{ type }}' => $constraint->type, '{{ value }}' => $constraintValue)
);
} else {
$context->expects($this->never())->method('addViolation');
}
Expand All @@ -54,17 +71,30 @@ public function testValidate($value, $violates, $defaultRegion = PhoneNumberUtil
/**
* 0 => Value
* 1 => Violates?
* 2 => Default region (optional)
* 2 => Type (optional)
* 3 => Default region (optional)
*/
public function validateProvider()
{
return array(
array(null, false),
array('', false),
array(PhoneNumberUtil::getInstance()->parse('+441234567890', PhoneNumberUtil::UNKNOWN_REGION), false),
array(PhoneNumberUtil::getInstance()->parse('+441234567890', PhoneNumberUtil::UNKNOWN_REGION), false, 'fixed_line'),
array(PhoneNumberUtil::getInstance()->parse('+441234567890', PhoneNumberUtil::UNKNOWN_REGION), true, 'mobile'),
array(PhoneNumberUtil::getInstance()->parse('+44123456789', PhoneNumberUtil::UNKNOWN_REGION), true),
array('+441234567890', false),
array('01234 567890', false, 'GB'),
array('+441234567890', false, 'fixed_line'),
array('+441234567890', true, 'mobile'),
array('+44123456789', true),
array('+44123456789', true, 'mobile'),
array('+12015555555', false),
array('+12015555555', false, 'fixed_line'),
array('+12015555555', false, 'mobile'),
array('2015555555', false, null, 'US'),
array('2015555555', false, 'fixed_line', 'US'),
array('2015555555', false, 'mobile', 'US'),
array('01234 567890', false, null, 'GB'),
array('foo', true),
);
}
Expand Down
39 changes: 37 additions & 2 deletions Validator/Constraints/PhoneNumber.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,42 @@
*/
class PhoneNumber extends Constraint
{
public $message = 'This value is not a valid {{ type }} number.';
public $type = 'phone';
const ANY = 'any';
const FIXED_LINE = 'fixed_line';
const MOBILE = 'mobile';

private $anyMessage = 'This value is not a valid phone number.';
private $fixedLineMessage = 'This value is not a valid fixed-line number.';
private $mobileMessage = 'This value is not a valid mobile number.';

public $message = null;
public $type = self::ANY;
public $defaultRegion = PhoneNumberUtil::UNKNOWN_REGION;

public function getType()
{
switch ($this->type) {
case self::FIXED_LINE:
case self::MOBILE:
return $this->type;
}

return self::ANY;
}

public function getMessage()
{
if (null !== $this->message) {
return $this->message;
}

switch ($this->type) {
case self::FIXED_LINE:
return $this->fixedLineMessage;
case self::MOBILE:
return $this->mobileMessage;
}

return $this->anyMessage;
}
}
28 changes: 26 additions & 2 deletions Validator/Constraints/PhoneNumberValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use libphonenumber\NumberParseException;
use libphonenumber\PhoneNumber as PhoneNumberObject;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberType;
use libphonenumber\PhoneNumberUtil;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
Expand Down Expand Up @@ -61,6 +62,29 @@ public function validate($value, Constraint $constraint)

return;
}

switch ($constraint->getType()) {
case PhoneNumber::FIXED_LINE:
$validTypes = array(PhoneNumberType::FIXED_LINE, PhoneNumberType::FIXED_LINE_OR_MOBILE);
break;
case PhoneNumber::MOBILE:
$validTypes = array(PhoneNumberType::MOBILE, PhoneNumberType::FIXED_LINE_OR_MOBILE);
break;
default:
$validTypes = array();
break;
}

if (count($validTypes)) {
$type = $phoneUtil->getNumberType($phoneNumber);

if (false === in_array($type, $validTypes)) {
$this->addViolation($value, $constraint);

return;
}

}
}

/**
Expand All @@ -72,8 +96,8 @@ public function validate($value, Constraint $constraint)
private function addViolation($value, Constraint $constraint)
{
$this->context->addViolation(
$constraint->message,
array('{{ type }}' => $constraint->type, '{{ value }}' => $value)
$constraint->getMessage(),
array('{{ type }}' => $constraint->getType(), '{{ value }}' => $value)
);
}
}

0 comments on commit 59d7d53

Please sign in to comment.