Skip to content

Commit

Permalink
Add 'simple' Address Validation class (#119)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
stefandoorn authored Sep 15, 2016
1 parent 5ec83a2 commit 077a271
Show file tree
Hide file tree
Showing 11 changed files with 417 additions and 27 deletions.
56 changes: 47 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,32 @@ Tracking API, Shipping API, Rating API and Time in Transit API. Feel free to con
3. [Address Validation Class](#addressvalidation-class)
* [Example](#addressvalidation-class-example)
* [Parameters](#addressvalidation-class-parameters)
4. [QuantumView Class](#quantumview-class)
4. [Simple Address Validation Class](#simple-addressvalidation-class)
* [Example](#simple-addressvalidation-class-example)
* [Parameters](#simple-addressvalidation-class-parameters)
5. [QuantumView Class](#quantumview-class)
* [Example](#quantumview-class-example)
* [Parameters](#quantumview-class-parameters)
5. [Tracking Class](#tracking-class)
6. [Tracking Class](#tracking-class)
* [Example](#tracking-class-example)
* [Parameters](#tracking-class-parameters)
6. [Rate Class](#rate-class)
7. [Rate Class](#rate-class)
* [Example](#rate-class-example)
* [Parameters](#rate-class-parameters)
7. [TimeInTransit Class](#timeintransit-class)
8. [TimeInTransit Class](#timeintransit-class)
* [Example](#timeintransit-class-example)
* [Parameters](#timeintransit-class-parameters)
8. [Locator Class](#locator-class)
9. [Locator Class](#locator-class)
* [Example](#locator-class-example)
* [Parameters](#locator-class-parameters)
9. [Tradeability Class](#tradeability-class)
10. [Tradeability Class](#tradeability-class)
* [Example](#tradeability-class-example)
* [Parameters](#tradeability-class-parameters)
10. [Shipping Class](#shipping-class)
11. [Shipping Class](#shipping-class)
* [Example](#shipping-class-example)
* [Parameters](#shipping-class-parameters)
11. [Logging](#logging)
12. [License](#license-section)
12. [Logging](#logging)
13. [License](#license-section)

<a name="requirements"></a>
## Requirements
Expand Down Expand Up @@ -133,6 +136,41 @@ Address Validation parameters are:
* `address` Address object as constructed in example
* `requestOption` One of the three request options. See documentation. Default = Address Validation.
* `maxSuggestion` Maximum number of suggestions to be returned. Max = 50

<a name="simple-addressvalidation-class"></a>
## Simple Address Validation Class

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.

Note: UPS has two Address Validations. This is supported in more countries, but offers less functionality.

Not all countries are supported, see UPS documentation.

<a name="simple-addressvalidation-class-example"></a>
### Example

```php
$address = new \Ups\Entity\Address();
$address->setStateProvinceCode('NY');
$address->setCity('New York');
$address->setCountryCode('US');
$address->setPostalCode('10000');

$av = new \Ups\SimpleAddressValidation($accessKey, $userId, $password);
try {
$response = $av->validate($address);
var_dump($response);
} catch (Exception $e) {
var_dump($e);
}
```

<a name="simpleaddressvalidation-class-parameters"></a>
### Parameters

Simple Address Validation parameters are:

* `address` Address object as constructed in example

<a name="quantumview-class"></a>
## QuantumView Class
Expand Down
12 changes: 8 additions & 4 deletions src/AddressValidation.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

/**
* Address Validation API Wrapper.
*
* This functionality is only available in USA, Puerto Rico & Canada.
*/
class AddressValidation extends Ups
{
Expand Down Expand Up @@ -43,6 +45,7 @@ class AddressValidation extends Ups
* @var int
*/
private $maxSuggestion;

/**
* @var bool
*/
Expand Down Expand Up @@ -92,18 +95,19 @@ public function deActivateReturnObjectOnValidate()
{
$this->useAVResponseObject = false;
}

/**
* Get address suggestions from UPS.
* Get address suggestions from UPS using the 'Street Level' Address Validation API (/XAV)
*
* @param $address
* @param Address $address
* @param int $requestOption
* @param int $maxSuggestion
*
* @throws Exception
*
* @return stdClass|AddressValidationResponse
*/
public function validate($address, $requestOption = self::REQUEST_OPTION_ADDRESS_VALIDATION, $maxSuggestion = 15)
public function validate(Address $address, $requestOption = self::REQUEST_OPTION_ADDRESS_VALIDATION, $maxSuggestion = 15)
{
if ($maxSuggestion > 50) {
throw new \Exception('Maximum of 50 suggestions allowed');
Expand Down Expand Up @@ -223,7 +227,7 @@ private function formatResponse(SimpleXMLElement $response)
public function getRequest()
{
if (null === $this->request) {
$this->request = new Request();
$this->request = new Request($this->logger);
}

return $this->request;
Expand Down
195 changes: 195 additions & 0 deletions src/SimpleAddressValidation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
<?php

namespace Ups;

use DOMDocument;
use Exception;
use Psr\Log\LoggerInterface;
use SimpleXMLElement;
use stdClass;
use Ups\Entity\Address;
use Ups\Entity\AddressValidationResponse;

/**
* Address Validation API Wrapper to use the basic Address Validation endpoints.
*
* This functionality is more basic, but available in more countries than the 'extended' Address Validation methods.
*/
class SimpleAddressValidation extends Ups
{
const ENDPOINT = '/AV';

/**
* @var RequestInterface
*/
private $request;

/**
* @var ResponseInterface
*
* @todo make private
*/
public $response;

/**
* @var Address
*/
private $address;

/**
* @param string|null $accessKey UPS License Access Key
* @param string|null $userId UPS User ID
* @param string|null $password UPS User Password
* @param bool $useIntegration Determine if we should use production or CIE URLs.
* @param RequestInterface|null $request
* @param LoggerInterface|null $logger PSR3 compatible logger (optional)
*/
public function __construct(
$accessKey = null,
$userId = null,
$password = null,
$useIntegration = false,
RequestInterface $request = null,
LoggerInterface $logger = null
) {
if (null !== $request) {
$this->setRequest($request);
}
parent::__construct($accessKey, $userId, $password, $useIntegration, $logger);
}

/**
* Get address suggestions from UPS using the default Address Validation API (/AV)
*
* @param Address $address
*
* @throws Exception
*
* @return array
*/
public function validate(Address $address)
{
$this->address = $address;

$access = $this->createAccess();
$request = $this->createRequest();

$this->response = $this->getRequest()->request($access, $request, $this->compileEndpointUrl(self::ENDPOINT));
$response = $this->response->getResponse();

if (null === $response) {
throw new Exception('Failure (0): Unknown error', 0);
}

if ($response instanceof SimpleXMLElement && $response->Response->ResponseStatusCode == 0) {
throw new Exception(
"Failure ({$response->Response->Error->ErrorSeverity}): {$response->Response->Error->ErrorDescription}",
(int)$response->Response->Error->ErrorCode
);
}

return $this->formatResponse($response);
}

/**
* Create the AV request.
*
* @return string
*/
private function createRequest()
{
$xml = new DOMDocument();
$xml->formatOutput = true;

$avRequest = $xml->appendChild($xml->createElement('AddressValidationRequest'));
$avRequest->setAttribute('xml:lang', 'en-US');

$request = $avRequest->appendChild($xml->createElement('Request'));

$node = $xml->importNode($this->createTransactionNode(), true);
$request->appendChild($node);

$request->appendChild($xml->createElement('RequestAction', 'AV'));

if (null !== $this->address) {
$addressNode = $avRequest->appendChild($xml->createElement('Address'));

if ($this->address->getStateProvinceCode()) {
$addressNode->appendChild($xml->createElement('StateProvinceCode', $this->address->getStateProvinceCode()));
}
if ($this->address->getCity()) {
$addressNode->appendChild($xml->createElement('City', $this->address->getCity()));
}
if ($this->address->getCountryCode()) {
$addressNode->appendChild($xml->createElement('CountryCode', $this->address->getCountryCode()));
}
if ($this->address->getPostalCode()) {
$addressNode->appendChild($xml->createElement('PostalCode', $this->address->getPostalCode()));
}
}

return $xml->saveXML();
}

/**
* Format the response.
*
* @param SimpleXMLElement $response
*
* @return array
*/
private function formatResponse(SimpleXMLElement $response)
{
$result = $this->convertXmlObject($response);

if (!is_array($result->AddressValidationResult)) {
return [$result->AddressValidationResult];
}

return $result->AddressValidationResult;
}

/**
* @return RequestInterface
*/
public function getRequest()
{
if (null === $this->request) {
$this->request = new Request($this->logger);
}

return $this->request;
}

/**
* @param RequestInterface $request
*
* @return $this
*/
public function setRequest(RequestInterface $request)
{
$this->request = $request;

return $this;
}

/**
* @return ResponseInterface
*/
public function getResponse()
{
return $this->response;
}

/**
* @param ResponseInterface $response
*
* @return $this
*/
public function setResponse(ResponseInterface $response)
{
$this->response = $response;

return $this;
}
}
Loading

0 comments on commit 077a271

Please sign in to comment.