Passed
Push — master ( 335c74...ca5aae )
by Pierre
02:52
created

deActivateReturnObjectOnValidate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 3
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
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.
15
 *
16
 * This functionality is only available in USA, Puerto Rico & Canada.
17
 */
18
class AddressValidation extends Ups
19
{
20
    const ENDPOINT = '/XAV';
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 int
36
     */
37
    private $requestOption;
38
39
    /**
40
     * @var Address
41
     */
42
    private $address;
43
44
    /**
45
     * @var int
46
     */
47
    private $maxSuggestion;
48
49
    /**
50
     * @var bool
51
     */
52
    private $useAVResponseObject = false;
53
54
    /**
55
     * Request Options.
56
     */
57
    const REQUEST_OPTION_ADDRESS_VALIDATION = 1;
58
    const REQUEST_OPTION_ADDRESS_CLASSIFICATION = 2;
59
    const REQUEST_OPTION_ADDRESS_VALIDATION_AND_CLASSIFICATION = 3;
60
61
    /**
62
     * @param string|null $accessKey UPS License Access Key
63
     * @param string|null $userId UPS User ID
64
     * @param string|null $password UPS User Password
65
     * @param bool $useIntegration Determine if we should use production or CIE URLs.
66
     * @param RequestInterface|null $request
67
     * @param LoggerInterface|null $logger PSR3 compatible logger (optional)
68
     */
69 View Code Duplication
    public function __construct(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
70
        $accessKey = null,
71
        $userId = null,
72
        $password = null,
73
        $useIntegration = false,
74
        RequestInterface $request = null,
75
        LoggerInterface $logger = null
76
    ) {
77
        if (null !== $request) {
78
            $this->setRequest($request);
79
        }
80
        parent::__construct($accessKey, $userId, $password, $useIntegration, $logger);
81
    }
82
83
    /**
84
     * Turn on returning of the AddressValidationResponse object
85
     */
86
    public function activateReturnObjectOnValidate()
87
    {
88
        $this->useAVResponseObject = true;
89
    }
90
91
    /**
92
     * Turn off returning of the AddressValidationResponse object
93
     */
94
    public function deActivateReturnObjectOnValidate()
95
    {
96
        $this->useAVResponseObject = false;
97
    }
98
99
    /**
100
     * Get address suggestions from UPS using the 'Street Level' Address Validation API (/XAV)
101
     *
102
     * @param Address $address
103
     * @param int $requestOption
104
     * @param int $maxSuggestion
105
     *
106
     * @throws Exception
107
     *
108
     * @return stdClass|AddressValidationResponse
109
     */
110
    public function validate(Address $address, $requestOption = self::REQUEST_OPTION_ADDRESS_VALIDATION, $maxSuggestion = 15)
111
    {
112
        if ($maxSuggestion > 50) {
113
            throw new \Exception('Maximum of 50 suggestions allowed');
114
        }
115
116
        if (!in_array($requestOption, range(1, 3))) {
117
            throw new \Exception('Invalid request option supplied');
118
        }
119
120
        $this->address = $address;
121
        $this->requestOption = $requestOption;
122
        $this->maxSuggestion = $maxSuggestion;
123
124
        $access = $this->createAccess();
125
        $request = $this->createRequest();
126
127
        $this->response = $this->getRequest()->request($access, $request, $this->compileEndpointUrl(self::ENDPOINT));
128
        $response = $this->response->getResponse();
129
130
        if (null === $response) {
131
            throw new Exception('Failure (0): Unknown error', 0);
132
        }
133
134
        if ($response instanceof SimpleXMLElement && $response->Response->ResponseStatusCode == 0) {
135
            throw new Exception(
136
                "Failure ({$response->Response->Error->ErrorSeverity}): {$response->Response->Error->ErrorDescription}",
137
                (int)$response->Response->Error->ErrorCode
138
            );
139
        }
140
        if ($this->useAVResponseObject) {
141
            unset($response->Response);
142
            $avResponse = new AddressValidationResponse($response, $requestOption);
143
            return $avResponse;
144
        }
145
        return $this->formatResponse($response);
146
    }
147
148
    /**
149
     * Create the XAV request.
150
     *
151
     * @return string
152
     */
153
    private function createRequest()
154
    {
155
        $xml = new DOMDocument();
156
        $xml->formatOutput = true;
157
158
        $avRequest = $xml->appendChild($xml->createElement('AddressValidationRequest'));
159
        $avRequest->setAttribute('xml:lang', 'en-US');
160
161
        $request = $avRequest->appendChild($xml->createElement('Request'));
162
163
        $node = $xml->importNode($this->createTransactionNode(), true);
164
        $request->appendChild($node);
165
166
        $request->appendChild($xml->createElement('RequestAction', 'XAV'));
167
168
        if (null !== $this->requestOption) {
169
            $request->appendChild($xml->createElement('RequestOption', $this->requestOption));
170
        }
171
172
        if (null !== $this->maxSuggestion) {
173
            $avRequest->appendChild($xml->createElement('MaximumListSize', $this->maxSuggestion));
174
        }
175
176
        if (null !== $this->address) {
177
            $addressNode = $avRequest->appendChild($xml->createElement('AddressKeyFormat'));
178
179
            if ($this->address->getAttentionName()) {
180
                $addressNode->appendChild($xml->createElement('ConsigneeName', $this->address->getAttentionName()));
181
            }
182
            if ($this->address->getBuildingName()) {
183
                $addressNode->appendChild($xml->createElement('BuildingName', $this->address->getBuildingName()));
184
            }
185
            if ($this->address->getAddressLine1()) {
186
                $addressNode->appendChild($xml->createElement('AddressLine', $this->address->getAddressLine1()));
187
            }
188
            if ($this->address->getAddressLine2()) {
189
                $addressNode->appendChild($xml->createElement('AddressLine', $this->address->getAddressLine2()));
190
            }
191
            if ($this->address->getAddressLine3()) {
192
                $addressNode->appendChild($xml->createElement('AddressLine', $this->address->getAddressLine3()));
193
            }
194
            if ($this->address->getStateProvinceCode()) {
195
                $addressNode->appendChild($xml->createElement('PoliticalDivision1',
196
                    $this->address->getStateProvinceCode()));
197
            }
198
            if ($this->address->getCity()) {
199
                $addressNode->appendChild($xml->createElement('PoliticalDivision2', $this->address->getCity()));
200
            }
201
            if ($this->address->getCountryCode()) {
202
                $addressNode->appendChild($xml->createElement('CountryCode', $this->address->getCountryCode()));
203
            }
204
            if ($this->address->getPostalCode()) {
205
                $addressNode->appendChild($xml->createElement('PostcodePrimaryLow', $this->address->getPostalCode()));
206
            }
207
        }
208
209
        return $xml->saveXML();
210
    }
211
212
    /**
213
     * Format the response.
214
     *
215
     * @param SimpleXMLElement $response
216
     *
217
     * @return stdClass
218
     */
219
    private function formatResponse(SimpleXMLElement $response)
220
    {
221
        return $this->convertXmlObject($response->AddressKeyFormat);
222
    }
223
224
    /**
225
     * @return RequestInterface
226
     */
227 View Code Duplication
    public function getRequest()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
228
    {
229
        if (null === $this->request) {
230
            $this->request = new Request($this->logger);
231
        }
232
233
        return $this->request;
234
    }
235
236
    /**
237
     * @param RequestInterface $request
238
     *
239
     * @return $this
240
     */
241
    public function setRequest(RequestInterface $request)
242
    {
243
        $this->request = $request;
244
245
        return $this;
246
    }
247
248
    /**
249
     * @return ResponseInterface
250
     */
251
    public function getResponse()
252
    {
253
        return $this->response;
254
    }
255
256
    /**
257
     * @param ResponseInterface $response
258
     *
259
     * @return $this
260
     */
261
    public function setResponse(ResponseInterface $response)
262
    {
263
        $this->response = $response;
264
265
        return $this;
266
    }
267
}
268