Completed
Push — master ( 9a09b4...963e96 )
by Dieter
05:50
created

analyzeSimpleResponseErrorCodeAndMessageStatusCode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 9
ccs 6
cts 6
cp 1
rs 9.6666
c 1
b 0
f 0
cc 1
eloc 6
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * amadeus-ws-client
4
 *
5
 * Copyright 2015 Amadeus Benelux NV
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 * http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 *
19
 * @package Amadeus
20
 * @license https://opensource.org/licenses/Apache-2.0 Apache 2.0
21
 */
22
23
namespace Amadeus\Client\ResponseHandler;
24
25
use Amadeus\Client\Exception;
26
use Amadeus\Client\Result;
27
use Amadeus\Client\Session\Handler\SendResult;
28
29
/**
30
 * The standard response handler for an individual message. Includes some basic functionality to build on.
31
 *
32
 * @package Amadeus\Client\ResponseHandler
33
 * @author Dieter Devlieghere <[email protected]>
34
 */
35
abstract class StandardResponseHandler implements MessageResponseHandler
36
{
37
    /**
38
     * Default namespace prefix we'll be using for xpath queries
39
     *
40
     * Why not "m"? It's as good as any other letter.
41
     */
42
    const XMLNS_PREFIX = "m";
43
44
    /**
45
     * Analyze response by looking for error, category and message with the provided XPATH queries
46
     *
47
     * xpath queries must be prefixed with the namespace self::XMLNS_PREFIX
48
     *
49
     * @param SendResult $response
50
     * @param string $qErr XPATH query for fetching error code (first node is used)
51
     * @param string $qCat XPATH query for fetching error category (first node is used)
52
     * @param string $qMsg XPATH query for fetching error messages (all nodes are used)
53
     * @return Result
54
     */
55 9
    protected function analyzeWithErrCodeCategoryMsgQuery(SendResult $response, $qErr, $qCat, $qMsg)
56
    {
57 9
        $analyzeResponse = new Result($response);
58
59 9
        $domXpath = $this->makeDomXpath($response->responseXml);
60
61 8
        $errorCodeNodeList = $domXpath->query($qErr);
62
63 8
        if ($errorCodeNodeList->length > 0) {
64 5
            $analyzeResponse->status = Result::STATUS_ERROR;
65
66 5
            $errorCatNode = $domXpath->query($qCat)->item(0);
67 5
            if ($errorCatNode instanceof \DOMNode) {
68 5
                $analyzeResponse->status = $this->makeStatusFromErrorQualifier($errorCatNode->nodeValue);
69 5
            }
70
71 5
            $analyzeResponse->messages[] = new Result\NotOk(
72 5
                $errorCodeNodeList->item(0)->nodeValue,
73 5
                $this->makeMessageFromMessagesNodeList(
74 5
                    $domXpath->query($qMsg)
75 5
                )
76 5
            );
77 5
        }
78
79 8
        return $analyzeResponse;
80
    }
81
82
    /**
83
     * Analyze response by looking for error, category and message in nodes specified by name
84
     *
85
     * @param SendResult $response
86
     * @param string $nodeErr Node name of the node containing the error code (first node is used)
87
     * @param string $nodeCat Node name of the node containing the error category (first node is used)
88
     * @param string $nodeMsg Node name of the node containing the error messages (all nodes are used)
89
     * @return Result
90
     */
91 27
    protected function analyzeWithErrCodeCategoryMsgNodeName(SendResult $response, $nodeErr, $nodeCat, $nodeMsg)
92
    {
93 27
        $analyzeResponse = new Result($response);
94
95 27
        $domDoc = $this->loadDomDocument($response->responseXml);
96
97 27
        $errorCodeNode = $domDoc->getElementsByTagName($nodeErr)->item(0);
98
99 27 View Code Duplication
        if (!is_null($errorCodeNode)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
100 21
            $errorCatNode = $domDoc->getElementsByTagName($nodeCat)->item(0);
101 21
            if ($errorCatNode instanceof \DOMNode) {
102 14
                $analyzeResponse->status = $this->makeStatusFromErrorQualifier($errorCatNode->nodeValue);
103 14
            } else {
104 7
                $analyzeResponse->status = Result::STATUS_ERROR;
105
            }
106
107 21
            $errorCode = $errorCodeNode->nodeValue;
108 21
            $errorTextNodeList = $domDoc->getElementsByTagName($nodeMsg);
109
110 21
            $analyzeResponse->messages[] = new Result\NotOk(
111 21
                $errorCode,
112 21
                $this->makeMessageFromMessagesNodeList($errorTextNodeList)
113 21
            );
114 21
        }
115
116 27
        return $analyzeResponse;
117
    }
118
119
    /**
120
     * @param SendResult $response WebService message Send Result
121
     * @return Result
122
     * @throws Exception
123
     */
124 24
    protected function analyzeSimpleResponseErrorCodeAndMessage($response)
125
    {
126 24
        return $this->analyzeWithErrCodeCategoryMsgNodeName(
127 24
            $response,
128 24
            "errorCode",
129 24
            "errorCategory",
130
            "freeText"
131 24
        );
132
    }
133
134
    /**
135
     * @param SendResult $response WebService message Send Result
136
     * @return Result
137
     * @throws Exception
138
     */
139 3
    protected function analyzeSimpleResponseErrorCodeAndMessageStatusCode($response)
140
    {
141 3
        return $this->analyzeWithErrCodeCategoryMsgNodeName(
142 3
            $response,
143 3
            "errorCode",
144 3
            "statusCode",
145
            "freeText"
146 3
        );
147
    }
148
149
    /**
150
     * Make a Xpath-queryable object for an XML string
151
     *
152
     * registers TNS namespace with prefix self::XMLNS_PREFIX
153
     *
154
     * @param string $response
155
     * @return \DOMXPath
156
     * @throws Exception when there's a problem loading the message
157
     */
158 42
    protected function makeDomXpath($response)
159
    {
160 42
        $domDoc = $this->loadDomDocument($response);
161 41
        $domXpath = new \DOMXPath($domDoc);
162
163 41
        $domXpath->registerNamespace(
164 41
            self::XMLNS_PREFIX,
165 41
            $domDoc->documentElement->lookupNamespaceUri(null)
166 41
        );
167
168 41
        return $domXpath;
169
    }
170
171
    /**
172
     * @param string $response
173
     * @return \DOMDocument
174
     * @throws Exception when there's a problem loading the message
175
     */
176 77
    protected function loadDomDocument($response)
177
    {
178 77
        $domDoc = new \DOMDocument('1.0', 'UTF-8');
179
180 77
        $loadResult = $domDoc->loadXML($response);
181 77
        if ($loadResult === false) {
182 1
            throw new Exception('Could not load response message into DOMDocument');
183
        }
184
185 76
        return $domDoc;
186
    }
187
188
    /**
189
     * Converts a status code found in an error message to the appropriate status level
190
     *
191
     * @param string $qualifier
192
     * @return string Result::STATUS_*
193
     */
194 34
    protected function makeStatusFromErrorQualifier($qualifier)
195
    {
196
        $statusQualMapping = [
197 34
            'INF' => Result::STATUS_INFO,
198 34
            'WEC' => Result::STATUS_WARN,
199 34
            'WZZ' => Result::STATUS_WARN, //Mutually defined warning
200 34
            'WA' => Result::STATUS_WARN, //Info line Warning - PNR_AddMultiElements
201 34
            'W' => Result::STATUS_WARN,
202 34
            'EC' => Result::STATUS_ERROR,
203 34
            'X' => Result::STATUS_ERROR,
204 34
            '001' => Result::STATUS_ERROR, //Air_MultiAvailability
205 34
            'O' => Result::STATUS_OK,
206
            'ZZZ' => Result::STATUS_UNKNOWN
207 34
        ];
208
209 34
        if (array_key_exists($qualifier, $statusQualMapping)) {
210 33
            $status = $statusQualMapping[$qualifier];
211 33
        } else {
212 1
            $status = Result::STATUS_UNKNOWN;
213
        }
214
215 34
        return $status;
216
    }
217
218
    /**
219
     * Convert a DomNodeList of nodes containing a (potentially partial) error message into a string.
220
     *
221
     * @param \DOMNodeList $errorTextNodeList
222
     * @return string|null
223
     */
224 36
    protected function makeMessageFromMessagesNodeList($errorTextNodeList)
225
    {
226 36
        return implode(
227 36
            ' - ',
228 36
            array_map(
229 36
                function ($item) {
230 35
                    return trim($item->nodeValue);
231 36
                },
232 36
                iterator_to_array($errorTextNodeList)
233 36
            )
234 36
        );
235
    }
236
}
237