Skip to content

Commit 077a271

Browse files
authored
Add 'simple' Address Validation class (#119)
* Add Simple Address Validation class * Always return array of results, even when only one result * Add logger to Address Validation classes, make sure an array is always returned & introduce unit tests for SimpleAddressValidation * Add documentation for new simple address validation class
1 parent 5ec83a2 commit 077a271

File tree

11 files changed

+417
-27
lines changed

11 files changed

+417
-27
lines changed

README.md

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,29 +21,32 @@ Tracking API, Shipping API, Rating API and Time in Transit API. Feel free to con
2121
3. [Address Validation Class](#addressvalidation-class)
2222
* [Example](#addressvalidation-class-example)
2323
* [Parameters](#addressvalidation-class-parameters)
24-
4. [QuantumView Class](#quantumview-class)
24+
4. [Simple Address Validation Class](#simple-addressvalidation-class)
25+
* [Example](#simple-addressvalidation-class-example)
26+
* [Parameters](#simple-addressvalidation-class-parameters)
27+
5. [QuantumView Class](#quantumview-class)
2528
* [Example](#quantumview-class-example)
2629
* [Parameters](#quantumview-class-parameters)
27-
5. [Tracking Class](#tracking-class)
30+
6. [Tracking Class](#tracking-class)
2831
* [Example](#tracking-class-example)
2932
* [Parameters](#tracking-class-parameters)
30-
6. [Rate Class](#rate-class)
33+
7. [Rate Class](#rate-class)
3134
* [Example](#rate-class-example)
3235
* [Parameters](#rate-class-parameters)
33-
7. [TimeInTransit Class](#timeintransit-class)
36+
8. [TimeInTransit Class](#timeintransit-class)
3437
* [Example](#timeintransit-class-example)
3538
* [Parameters](#timeintransit-class-parameters)
36-
8. [Locator Class](#locator-class)
39+
9. [Locator Class](#locator-class)
3740
* [Example](#locator-class-example)
3841
* [Parameters](#locator-class-parameters)
39-
9. [Tradeability Class](#tradeability-class)
42+
10. [Tradeability Class](#tradeability-class)
4043
* [Example](#tradeability-class-example)
4144
* [Parameters](#tradeability-class-parameters)
42-
10. [Shipping Class](#shipping-class)
45+
11. [Shipping Class](#shipping-class)
4346
* [Example](#shipping-class-example)
4447
* [Parameters](#shipping-class-parameters)
45-
11. [Logging](#logging)
46-
12. [License](#license-section)
48+
12. [Logging](#logging)
49+
13. [License](#license-section)
4750

4851
<a name="requirements"></a>
4952
## Requirements
@@ -133,6 +136,41 @@ Address Validation parameters are:
133136
* `address` Address object as constructed in example
134137
* `requestOption` One of the three request options. See documentation. Default = Address Validation.
135138
* `maxSuggestion` Maximum number of suggestions to be returned. Max = 50
139+
140+
<a name="simple-addressvalidation-class"></a>
141+
## Simple Address Validation Class
142+
143+
The Address Validation Class allow you to validate less extensive as the previous class, but it's supported in more countries. It returns a quality score of the supplied address and provides alternatives.
144+
145+
Note: UPS has two Address Validations. This is supported in more countries, but offers less functionality.
146+
147+
Not all countries are supported, see UPS documentation.
148+
149+
<a name="simple-addressvalidation-class-example"></a>
150+
### Example
151+
152+
```php
153+
$address = new \Ups\Entity\Address();
154+
$address->setStateProvinceCode('NY');
155+
$address->setCity('New York');
156+
$address->setCountryCode('US');
157+
$address->setPostalCode('10000');
158+
159+
$av = new \Ups\SimpleAddressValidation($accessKey, $userId, $password);
160+
try {
161+
$response = $av->validate($address);
162+
var_dump($response);
163+
} catch (Exception $e) {
164+
var_dump($e);
165+
}
166+
```
167+
168+
<a name="simpleaddressvalidation-class-parameters"></a>
169+
### Parameters
170+
171+
Simple Address Validation parameters are:
172+
173+
* `address` Address object as constructed in example
136174

137175
<a name="quantumview-class"></a>
138176
## QuantumView Class

src/AddressValidation.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
/**
1414
* Address Validation API Wrapper.
15+
*
16+
* This functionality is only available in USA, Puerto Rico & Canada.
1517
*/
1618
class AddressValidation extends Ups
1719
{
@@ -43,6 +45,7 @@ class AddressValidation extends Ups
4345
* @var int
4446
*/
4547
private $maxSuggestion;
48+
4649
/**
4750
* @var bool
4851
*/
@@ -92,18 +95,19 @@ public function deActivateReturnObjectOnValidate()
9295
{
9396
$this->useAVResponseObject = false;
9497
}
98+
9599
/**
96-
* Get address suggestions from UPS.
100+
* Get address suggestions from UPS using the 'Street Level' Address Validation API (/XAV)
97101
*
98-
* @param $address
102+
* @param Address $address
99103
* @param int $requestOption
100104
* @param int $maxSuggestion
101105
*
102106
* @throws Exception
103107
*
104108
* @return stdClass|AddressValidationResponse
105109
*/
106-
public function validate($address, $requestOption = self::REQUEST_OPTION_ADDRESS_VALIDATION, $maxSuggestion = 15)
110+
public function validate(Address $address, $requestOption = self::REQUEST_OPTION_ADDRESS_VALIDATION, $maxSuggestion = 15)
107111
{
108112
if ($maxSuggestion > 50) {
109113
throw new \Exception('Maximum of 50 suggestions allowed');
@@ -223,7 +227,7 @@ private function formatResponse(SimpleXMLElement $response)
223227
public function getRequest()
224228
{
225229
if (null === $this->request) {
226-
$this->request = new Request();
230+
$this->request = new Request($this->logger);
227231
}
228232

229233
return $this->request;

src/SimpleAddressValidation.php

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
<?php
2+
3+
namespace Ups;
4+
5+
use DOMDocument;
6+
use Exception;
7+
use Psr\Log\LoggerInterface;
8+
use SimpleXMLElement;
9+
use stdClass;
10+
use Ups\Entity\Address;
11+
use Ups\Entity\AddressValidationResponse;
12+
13+
/**
14+
* Address Validation API Wrapper to use the basic Address Validation endpoints.
15+
*
16+
* This functionality is more basic, but available in more countries than the 'extended' Address Validation methods.
17+
*/
18+
class SimpleAddressValidation extends Ups
19+
{
20+
const ENDPOINT = '/AV';
21+
22+
/**
23+
* @var RequestInterface
24+
*/
25+
private $request;
26+
27+
/**
28+
* @var ResponseInterface
29+
*
30+
* @todo make private
31+
*/
32+
public $response;
33+
34+
/**
35+
* @var Address
36+
*/
37+
private $address;
38+
39+
/**
40+
* @param string|null $accessKey UPS License Access Key
41+
* @param string|null $userId UPS User ID
42+
* @param string|null $password UPS User Password
43+
* @param bool $useIntegration Determine if we should use production or CIE URLs.
44+
* @param RequestInterface|null $request
45+
* @param LoggerInterface|null $logger PSR3 compatible logger (optional)
46+
*/
47+
public function __construct(
48+
$accessKey = null,
49+
$userId = null,
50+
$password = null,
51+
$useIntegration = false,
52+
RequestInterface $request = null,
53+
LoggerInterface $logger = null
54+
) {
55+
if (null !== $request) {
56+
$this->setRequest($request);
57+
}
58+
parent::__construct($accessKey, $userId, $password, $useIntegration, $logger);
59+
}
60+
61+
/**
62+
* Get address suggestions from UPS using the default Address Validation API (/AV)
63+
*
64+
* @param Address $address
65+
*
66+
* @throws Exception
67+
*
68+
* @return array
69+
*/
70+
public function validate(Address $address)
71+
{
72+
$this->address = $address;
73+
74+
$access = $this->createAccess();
75+
$request = $this->createRequest();
76+
77+
$this->response = $this->getRequest()->request($access, $request, $this->compileEndpointUrl(self::ENDPOINT));
78+
$response = $this->response->getResponse();
79+
80+
if (null === $response) {
81+
throw new Exception('Failure (0): Unknown error', 0);
82+
}
83+
84+
if ($response instanceof SimpleXMLElement && $response->Response->ResponseStatusCode == 0) {
85+
throw new Exception(
86+
"Failure ({$response->Response->Error->ErrorSeverity}): {$response->Response->Error->ErrorDescription}",
87+
(int)$response->Response->Error->ErrorCode
88+
);
89+
}
90+
91+
return $this->formatResponse($response);
92+
}
93+
94+
/**
95+
* Create the AV request.
96+
*
97+
* @return string
98+
*/
99+
private function createRequest()
100+
{
101+
$xml = new DOMDocument();
102+
$xml->formatOutput = true;
103+
104+
$avRequest = $xml->appendChild($xml->createElement('AddressValidationRequest'));
105+
$avRequest->setAttribute('xml:lang', 'en-US');
106+
107+
$request = $avRequest->appendChild($xml->createElement('Request'));
108+
109+
$node = $xml->importNode($this->createTransactionNode(), true);
110+
$request->appendChild($node);
111+
112+
$request->appendChild($xml->createElement('RequestAction', 'AV'));
113+
114+
if (null !== $this->address) {
115+
$addressNode = $avRequest->appendChild($xml->createElement('Address'));
116+
117+
if ($this->address->getStateProvinceCode()) {
118+
$addressNode->appendChild($xml->createElement('StateProvinceCode', $this->address->getStateProvinceCode()));
119+
}
120+
if ($this->address->getCity()) {
121+
$addressNode->appendChild($xml->createElement('City', $this->address->getCity()));
122+
}
123+
if ($this->address->getCountryCode()) {
124+
$addressNode->appendChild($xml->createElement('CountryCode', $this->address->getCountryCode()));
125+
}
126+
if ($this->address->getPostalCode()) {
127+
$addressNode->appendChild($xml->createElement('PostalCode', $this->address->getPostalCode()));
128+
}
129+
}
130+
131+
return $xml->saveXML();
132+
}
133+
134+
/**
135+
* Format the response.
136+
*
137+
* @param SimpleXMLElement $response
138+
*
139+
* @return array
140+
*/
141+
private function formatResponse(SimpleXMLElement $response)
142+
{
143+
$result = $this->convertXmlObject($response);
144+
145+
if (!is_array($result->AddressValidationResult)) {
146+
return [$result->AddressValidationResult];
147+
}
148+
149+
return $result->AddressValidationResult;
150+
}
151+
152+
/**
153+
* @return RequestInterface
154+
*/
155+
public function getRequest()
156+
{
157+
if (null === $this->request) {
158+
$this->request = new Request($this->logger);
159+
}
160+
161+
return $this->request;
162+
}
163+
164+
/**
165+
* @param RequestInterface $request
166+
*
167+
* @return $this
168+
*/
169+
public function setRequest(RequestInterface $request)
170+
{
171+
$this->request = $request;
172+
173+
return $this;
174+
}
175+
176+
/**
177+
* @return ResponseInterface
178+
*/
179+
public function getResponse()
180+
{
181+
return $this->response;
182+
}
183+
184+
/**
185+
* @param ResponseInterface $response
186+
*
187+
* @return $this
188+
*/
189+
public function setResponse(ResponseInterface $response)
190+
{
191+
$this->response = $response;
192+
193+
return $this;
194+
}
195+
}

0 commit comments

Comments
 (0)