Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

- phone numbers in Canada are of the same format as those in the USA.… #146

Open
wants to merge 4 commits into
base: 4.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 148 additions & 1 deletion src/Validation/CaValidation.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,56 @@ public static function postal($check)
*/
public static function phone($check)
{
throw new NotImplementedException(__d('localized', '%s Not implemented yet.'));
$invalid_num = new InvalidNumberRule();

$invalid_num->add(null, 're[0-9]11', null, null);
$invalid_num->add(null, null, 're[0-9]11', null);
$invalid_num->add(null, 're[01][0-9][0-9]', null, null);
$invalid_num->add(null, null, 're[01][0-9][0-9]', null);
$invalid_num->add(null, null, 555, 'ra0100-0199');

// Unassigned area codes (incomplete)
$invalid_num->add(null, 'ra221-223', null, null);
$invalid_num->add(null, '230', null, null);
$invalid_num->add(null, 'ra232-233', null, null);
$invalid_num->add(null, '235', null, null);
$invalid_num->add(null, 'ra237-238', null, null);
$invalid_num->add(null, '241', null, null);
$invalid_num->add(null, 'ra243-245', null, null);
$invalid_num->add(null, '247', null, null);
$invalid_num->add(null, '255', null, null);
$invalid_num->add(null, 'ra257-259', null, null);
$invalid_num->add(null, '261', null, null);
$invalid_num->add(null, '263', null, null);
$invalid_num->add(null, 'ra265-266', null, null);
$invalid_num->add(null, '271', null, null);
$invalid_num->add(null, '273', null, null);
$invalid_num->add(null, '275', null, null);
$invalid_num->add(null, 'ra277-280', null, null);
$invalid_num->add(null, '282', null, null);
$invalid_num->add(null, 'ra285-288', null, null);
$invalid_num->add(null, 'ra290-300', null, null);
$invalid_num->add(null, 'ra370-379', null, null);
$invalid_num->add(null, '555', null, null);
$invalid_num->add(null, '595', null, null);
$invalid_num->add(null, '962', null, null);

// Basic phone number pattern matching
$pattern = '/^(?:(?<country_code>\+?1\s*(?:[.-]\s*)?)?';
$pattern .= '(?<area_code>\(\s*([0-9][0-9][0-9])\s*\)|([0-9][0-9][0-9]))\s*(?:[.-]\s*)?)';
$pattern .= '(?<coe_code>[0-9][0-9][0-9])\s*(?:[.-]\s*)';
$pattern .= '?(?<subscriber_code>[0-9]{4})';
$pattern .= '(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$/';

$passed_simple = (bool)preg_match($pattern, $check, $captured);

$is_valid = false;

if ($passed_simple) {
$is_valid = $invalid_num->isNumberValid($captured['country_code'], $captured['area_code'], $captured['coe_code'], $captured['subscriber_code']);
}

return $is_valid;
}

/**
Expand All @@ -59,3 +108,101 @@ public static function personId($check)
throw new NotImplementedException(__d('localized', '%s Not implemented yet.'));
}
}

class InvalidNumberRule
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you implement this now? The previous PR was good to go, but now you introduce a lot of debatable code pieces here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that a separate class over regexp wouldn't be a viable option, but this looks like a snowflake between all the other validation rules if not applied on a more discussed and global level.

Copy link
Author

@jazty jazty Jan 26, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed it to my own fork. Didn't think it would trickle down... I just needed something more robust and the regex was not working for some real area codes (likewise, it let some invalid area codes through). You can ignore it... or is there something I can do to hide it? I'll look into that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can rebase, sqash and we can sure merge it then for now :) Thx.

{
private $number_rules = [];

public function add($country_code=null, $area_code=null, $coe_code=null, $subscriber_code=null) {
$number_rule = [
'country_code' => $country_code,
'area_code' => $area_code,
'coe_code' => $coe_code,
'subscriber_code' => $subscriber_code,
];

array_push($this->number_rules, $number_rule);
}

public function isNumberValid($country_code=null, $area_code=null, $coe_code=null, $subscriber_code=null) {
$phone_num_components = [
'country_code' => $country_code,
'area_code' => $area_code,
'coe_code' => $coe_code,
'subscriber_code' => $subscriber_code
];

$chars_to_remove = ['+', '-', '.', '(', ')'];

foreach ($this->number_rules as $number_rule) {
$break = false;
$is_valid = [
'country_code' => true,
'area_code' => true,
'coe_code' => true,
'subscriber_code' => true
];

$false_counts = 0;
foreach ($number_rule as $number_rule_component) {
if ($number_rule_component != null) {
$false_counts++;
}
}

foreach ($phone_num_components as $code_name => $code_value) {
$search_code = substr($number_rule[$code_name], 0, 2);
$code_value = str_replace($chars_to_remove, '', $code_value);

// Check for a search code then remove it if it exists.
if ($search_code == 're' || $search_code == 'ra') {
$number_rule[$code_name] = substr($number_rule[$code_name], 2);
}

if ($number_rule[$code_name] != null) {
// Search code is a regex.
if ($search_code == 're') {

if ((bool)preg_match('/^'.$number_rule[$code_name].'$/', $code_value)) {
$is_valid[$code_name] = false;
$break = true;
}
// Search code is a range.
} else if ($search_code == 'ra') {
list($start, $end) = explode('-', $number_rule[$code_name]);
for ($i = $start; $i <= $end; $i+=1) {
if ($i == $code_value) {
$is_valid[$code_name] = false;
$break = true;
}
}
// No search code. Just a number.
} else {
if ($number_rule[$code_name] == $code_value) {
$is_valid[$code_name] = false;
$break = true;
}
}
}

}
if ($break) {
break;
}
}

$num_of_falses = 0;
foreach ($is_valid as $is_valid_component) {
if ($is_valid_component == false) {
$num_of_falses++;
}
}

if ($num_of_falses == $false_counts) {
return false;
} else {
return true;
}
}
}

57 changes: 57 additions & 0 deletions tests/TestCase/Validation/CaValidationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,63 @@
*/
class CaValidationTest extends TestCase
{
/**
* test the phone method of CaValidation
*
* @return void
*/
public function testPhone()
{
$this->assertTrue(CaValidation::phone('+1 702 425 5085'));
$this->assertFalse(CaValidation::phone('teststring'));
$this->assertFalse(CaValidation::phone('1-(33)-(333)-(4444)'));
$this->assertFalse(CaValidation::phone('1-(33)-3333-4444'));
$this->assertFalse(CaValidation::phone('1-(33)-33-4444'));
$this->assertFalse(CaValidation::phone('1-(33)-3-44444'));
$this->assertFalse(CaValidation::phone('1-(33)-3-444'));
$this->assertFalse(CaValidation::phone('1-(33)-3-44'));

$this->assertFalse(CaValidation::phone('(055) 999-9999'));
$this->assertFalse(CaValidation::phone('(155) 999-9999'));
$this->assertFalse(CaValidation::phone('(595) 999-9999'));
$this->assertFalse(CaValidation::phone('(213) 099-9999'));
$this->assertFalse(CaValidation::phone('(213) 199-9999'));

// invalid area-codes
$this->assertFalse(CaValidation::phone('1-(511)-999-9999'));
$this->assertFalse(CaValidation::phone('1-(379)-999-9999'));
$this->assertFalse(CaValidation::phone('1-(962)-999-9999'));
$this->assertFalse(CaValidation::phone('1-(295)-999-9999'));
$this->assertFalse(CaValidation::phone('1-(222)-248-9999'));
$this->assertFalse(CaValidation::phone('1 555 999-9999'));

// invalid exhange
$this->assertFalse(CaValidation::phone('1-(705)-511-9999'));

// fictitious phone numbers
$this->assertFalse(CaValidation::phone('1-(705)-555-0199'));
$this->assertFalse(CaValidation::phone('1-(705)-555-0122'));

// valid phone numbers
$this->assertTrue(CaValidation::phone('1-(369)-333-4444'));
$this->assertTrue(CaValidation::phone('1-(973)-333-4444'));
$this->assertTrue(CaValidation::phone('1-(313)-555-9999'));
$this->assertTrue(CaValidation::phone('1-(705)-555-0299'));

$this->assertTrue(CaValidation::phone('1 (705) 333 4444'));
$this->assertTrue(CaValidation::phone('+1 (705) 333 4444'));
$this->assertTrue(CaValidation::phone('(705) 333 4444'));

$this->assertTrue(CaValidation::phone('1-(333)-333-4444'));
$this->assertTrue(CaValidation::phone('1.(333)-333-4444'));
$this->assertTrue(CaValidation::phone('1.(333).333-4444'));
$this->assertTrue(CaValidation::phone('1.(333).333.4444'));
$this->assertTrue(CaValidation::phone('1-333-333-4444'));
$this->assertFalse(CaValidation::phone('7002 425 5085'));
$this->assertTrue(CaValidation::phone('1 (705) 248 3242'));
$this->assertFalse(CaValidation::phone('1 %705# 248 3242'));
}

/**
* test the postal method of CaValidation
*
Expand Down