src/AddressValidation.php
<?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.
*
* This functionality is only available in USA, Puerto Rico & Canada.
*/
class AddressValidation extends Ups
{
const ENDPOINT = '/XAV';
/**
* @var RequestInterface
*/
private $request;
/**
* @var ResponseInterface
*
* @todo make private
*/
public $response;
/**
* @var int
*/
private $requestOption;
/**
* @var Address
*/
private $address;
/**
* @var int
*/
private $maxSuggestion;
/**
* @var bool
*/
private $useAVResponseObject = false;
/**
* Request Options.
*/
const REQUEST_OPTION_ADDRESS_VALIDATION = 1;
const REQUEST_OPTION_ADDRESS_CLASSIFICATION = 2;
const REQUEST_OPTION_ADDRESS_VALIDATION_AND_CLASSIFICATION = 3;
/**
* @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);
}
/**
* Turn on returning of the AddressValidationResponse object
*/
public function activateReturnObjectOnValidate()
{
$this->useAVResponseObject = true;
}
/**
* Turn off returning of the AddressValidationResponse object
*/
public function deActivateReturnObjectOnValidate()
{
$this->useAVResponseObject = false;
}
/**
* Get address suggestions from UPS using the 'Street Level' Address Validation API (/XAV)
*
* @param Address $address
* @param int $requestOption
* @param int $maxSuggestion
*
* @throws Exception
*
* @return stdClass|AddressValidationResponse
*/
public function validate(Address $address, $requestOption = self::REQUEST_OPTION_ADDRESS_VALIDATION, $maxSuggestion = 15)
{
if ($maxSuggestion > 50) {
throw new \Exception('Maximum of 50 suggestions allowed');
}
if (!in_array($requestOption, range(1, 3))) {
throw new \Exception('Invalid request option supplied');
}
$this->address = $address;
$this->requestOption = $requestOption;
$this->maxSuggestion = $maxSuggestion;
$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
);
}
if ($this->useAVResponseObject) {
unset($response->Response);
$avResponse = new AddressValidationResponse($response, $requestOption);
return $avResponse;
}
return $this->formatResponse($response);
}
/**
* Create the XAV 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', 'XAV'));
if (null !== $this->requestOption) {
$request->appendChild($xml->createElement('RequestOption', $this->requestOption));
}
if (null !== $this->maxSuggestion) {
$avRequest->appendChild($xml->createElement('MaximumListSize', $this->maxSuggestion));
}
if (null !== $this->address) {
$addressNode = $avRequest->appendChild($xml->createElement('AddressKeyFormat'));
if ($this->address->getAttentionName()) {
$addressNode->appendChild($xml->createElement('ConsigneeName', $this->address->getAttentionName()));
}
if ($this->address->getBuildingName()) {
$addressNode->appendChild($xml->createElement('BuildingName', $this->address->getBuildingName()));
}
if ($this->address->getAddressLine1()) {
$addressNode->appendChild($xml->createElement('AddressLine', $this->address->getAddressLine1()));
}
if ($this->address->getAddressLine2()) {
$addressNode->appendChild($xml->createElement('AddressLine', $this->address->getAddressLine2()));
}
if ($this->address->getAddressLine3()) {
$addressNode->appendChild($xml->createElement('AddressLine', $this->address->getAddressLine3()));
}
if ($this->address->getStateProvinceCode()) {
$addressNode->appendChild($xml->createElement(
'PoliticalDivision1',
$this->address->getStateProvinceCode()
));
}
if ($this->address->getCity()) {
$addressNode->appendChild($xml->createElement('PoliticalDivision2', $this->address->getCity()));
}
if ($this->address->getCountryCode()) {
$addressNode->appendChild($xml->createElement('CountryCode', $this->address->getCountryCode()));
}
if ($this->address->getPostalCode()) {
$addressNode->appendChild($xml->createElement('PostcodePrimaryLow', $this->address->getPostalCode()));
}
}
return $xml->saveXML();
}
/**
* Format the response.
*
* @param SimpleXMLElement $response
*
* @return stdClass
*/
private function formatResponse(SimpleXMLElement $response)
{
return $this->convertXmlObject($response->AddressKeyFormat);
}
/**
* @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;
}
}