Skip to content

Commit 4d52771

Browse files
authored
add postal code checker service (#8)
1 parent 48528d3 commit 4d52771

File tree

5 files changed

+226
-0
lines changed

5 files changed

+226
-0
lines changed

Checker/AddressUnderCheck.php

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<?php
2+
3+
namespace Markup\AddressingBundle\Checker;
4+
5+
use Markup\Addressing\AddressInterface;
6+
7+
class AddressUnderCheck implements AddressInterface
8+
{
9+
/**
10+
* @var string
11+
*/
12+
private $postalCode;
13+
14+
/**
15+
* @var string
16+
*/
17+
private $country;
18+
19+
/**
20+
* @param string $postalCode
21+
* @param string $country
22+
*/
23+
public function __construct($postalCode, $country)
24+
{
25+
$this->postalCode = $postalCode;
26+
$this->country = $country;
27+
}
28+
29+
/**
30+
* Gets a name for the recipient at this address. Returns null if one is not specified.
31+
*
32+
* @return string|null
33+
**/
34+
public function getRecipient()
35+
{
36+
return null;
37+
}
38+
39+
/**
40+
* Gets whether the address has a recipient defined.
41+
*
42+
* @return bool
43+
**/
44+
public function hasRecipient()
45+
{
46+
return false;// TODO: Implement hasRecipient() method.
47+
}
48+
49+
/**
50+
* Gets the numbered address line, counting from one. If there is no address line for provided number, return null.
51+
*
52+
* @param int $lineNumber
53+
* @return string|null
54+
**/
55+
public function getStreetAddressLine($lineNumber)
56+
{
57+
return null;
58+
}
59+
60+
/**
61+
* Gets the address lines that are part of the street address - i.e. everything up until the postal town.
62+
*
63+
* @return array
64+
**/
65+
public function getStreetAddressLines()
66+
{
67+
return [];
68+
}
69+
70+
/**
71+
* Gets the locality for this address. This field is often referred to as a "town" or a "city".
72+
*
73+
* @return string
74+
**/
75+
public function getLocality()
76+
{
77+
return '';
78+
}
79+
80+
/**
81+
* Gets the region for this address. This field is often referred to as a "county", "state" or "province".
82+
* If no region is indicated as part of the address information, returns an empty string.
83+
*
84+
* @return string
85+
**/
86+
public function getRegion()
87+
{
88+
return '';
89+
}
90+
91+
/**
92+
* Gets the postal code for this address.
93+
* If no postal code is indicated as part of the address information, returns an empty string.
94+
*
95+
* @return string
96+
**/
97+
public function getPostalCode()
98+
{
99+
return $this->postalCode;
100+
}
101+
102+
/**
103+
* Gets the ISO-3166-2 (alpha-2) representation of the country indicated for this address.
104+
* i.e. 'GB' for United Kingdom (*not* 'UK'), 'US' for United States.
105+
*
106+
* @return string
107+
**/
108+
public function getCountry()
109+
{
110+
return $this->country;
111+
}
112+
}

Checker/PostalCodeChecker.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
namespace Markup\AddressingBundle\Checker;
4+
5+
use Markup\Addressing\Canonicalizer\PostalCodeCanonicalizer;
6+
use Symfony\Component\Validator\Validator\ValidatorInterface;
7+
8+
/**
9+
* A checker service that can take a postal code and a country, and check whether the postal code is recognisable as one.
10+
*/
11+
class PostalCodeChecker
12+
{
13+
/**
14+
* @var ValidatorInterface
15+
*/
16+
private $validator;
17+
18+
/**
19+
* @param ValidatorInterface $validator
20+
*/
21+
public function __construct(ValidatorInterface $validator)
22+
{
23+
$this->validator = $validator;
24+
}
25+
26+
/**
27+
* @param string $postalCode
28+
* @param string $country
29+
* @return bool
30+
*/
31+
public function check($postalCode, $country)
32+
{
33+
$violationList = $this->validator->validate(
34+
new AddressUnderCheck(
35+
$this->canonicalize($postalCode, $country),
36+
$country
37+
)
38+
);
39+
40+
return count($violationList) === 0;
41+
}
42+
43+
private function canonicalize($postalCode, $country)
44+
{
45+
return (new PostalCodeCanonicalizer())->canonicalizeForCountry($postalCode, $country);
46+
}
47+
}

Resources/config/services.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,7 @@ services:
123123
- '%markup_addressing.require_strict_regions%'
124124
tags:
125125
- { name: validator.constraint_validator, alias: addressing_region }
126+
markup_addressing.postal_code_checker:
127+
class: 'Markup\AddressingBundle\Checker\PostalCodeChecker'
128+
arguments:
129+
- '@validator'

Resources/config/validation.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Markup\AddressingBundle\Checker\AddressUnderCheck:
2+
properties:
3+
country:
4+
- Regex:
5+
pattern: '/[A-Z]{2}/'
6+
constraints:
7+
- Markup\AddressingBundle\Validator\PostalCodeValidator: ~
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
namespace Markup\AddressingBundle\Tests\Checker;
4+
5+
use Markup\AddressingBundle\Checker\AddressUnderCheck;
6+
use Markup\AddressingBundle\Checker\PostalCodeChecker;
7+
use Mockery as m;
8+
use Symfony\Component\Validator\ConstraintViolationInterface;
9+
use Symfony\Component\Validator\ConstraintViolationList;
10+
use Symfony\Component\Validator\Validator\ValidatorInterface;
11+
12+
class PostalCodeCheckerTest extends \PHPUnit_Framework_TestCase
13+
{
14+
/**
15+
* @var ValidatorInterface
16+
*/
17+
private $validator;
18+
19+
/**
20+
* @var PostalCodeChecker
21+
*/
22+
private $checker;
23+
24+
protected function setUp()
25+
{
26+
$this->validator = m::mock(ValidatorInterface::class);
27+
$this->checker = new PostalCodeChecker($this->validator);
28+
}
29+
30+
protected function tearDown()
31+
{
32+
m::close();
33+
}
34+
35+
public function testPostalCodeCheckerTrueIfValidates()
36+
{
37+
$emptyViolationList = new ConstraintViolationList();
38+
$this->validator
39+
->shouldReceive('validate')
40+
->with(m::type(AddressUnderCheck::class))
41+
->once()
42+
->andReturn($emptyViolationList);
43+
$this->assertTrue($this->checker->check('sw1a1aa', 'GB'));
44+
}
45+
46+
public function testPostalCodeCheckerFalseIfDoesNotValidate()
47+
{
48+
$nonEmptyViolationList = new ConstraintViolationList([m::mock(ConstraintViolationInterface::class)]);
49+
$this->validator
50+
->shouldReceive('validate')
51+
->with(m::type(AddressUnderCheck::class))
52+
->once()
53+
->andReturn($nonEmptyViolationList);
54+
$this->assertFalse($this->checker->check('123456', 'SE'));
55+
}
56+
}

0 commit comments

Comments
 (0)