Completed
Push — master ( dd7fb7...8b5d0e )
by Dieter
06:44
created

Base   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 424
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 9

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 33
lcom 2
cbo 9
dl 0
loc 424
ccs 126
cts 126
cp 1
rs 9.3999
c 0
b 0
f 0

21 Methods

Rating   Name   Duplication   Size   Complexity  
A getSessionData() 0 4 1
A setSessionData() 0 13 2
A __construct() 0 12 3
B sendMessage() 0 39 3
prepareForNextMessage() 0 1 ?
handlePostMessage() 0 1 ?
A getLastRequest() 0 7 1
A getLastResponse() 0 7 1
A getLastRequestHeaders() 0 7 1
A getLastResponseHeaders() 0 7 1
A getOriginatorOffice() 0 4 1
A getMessagesAndVersions() 0 8 2
A loadMessagesAndVersions() 0 6 1
A getActiveVersionFor() 0 12 3
A getWsdlIdFor() 0 10 3
A getSoapClient() 0 14 4
A initSoapClient() 0 12 1
makeSoapClientOptions() 0 1 ?
A executeMethodOnSoapClientForMsg() 0 11 2
A logRequestAndResponse() 0 11 1
A log() 0 8 2
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\Session\Handler;
24
25
use Amadeus\Client;
26
use Amadeus\Client\Struct\BaseWsMessage;
27
use Amadeus\Client\Params\SessionHandlerParams;
28
use Psr\Log\LoggerAwareInterface;
29
use Psr\Log\LoggerAwareTrait;
30
use Psr\Log\LoggerInterface;
31
use Psr\Log\LogLevel;
32
use Psr\Log\NullLogger;
33
34
/**
35
 * Base Session Handler
36
 *
37
 * Session handler will manage everything related to the session with the Amadeus Web Services server:
38
 * - be configurable to handle different versions of authentication mechanisms depending on the WSDL received
39
 * - decide if a separate authentication message is needed and if so, send it
40
 *
41
 * @package Amadeus\Client\Session\Handler
42
 * @author Dieter Devlieghere <[email protected]>
43
 */
44
abstract class Base implements HandlerInterface, LoggerAwareInterface
45
{
46
    use LoggerAwareTrait;
47
48
    /**
49
     * Status variable to know wether the given session is in a certain context.
50
     *
51
     * @todo implement this feature - currently the application using the client must know the context itself.
52
     * @var bool
53
     */
54
    protected $hasContext = false;
55
56
    /**
57
     * The context of the currently active session
58
     *
59
     * @todo implement this feature - currently the application using the client must know the context itself.
60
     * @var mixed
61
     */
62
    protected $context;
63
64
    /**
65
     * Session information:
66
     * - session ID
67
     * - sequence number
68
     * - security Token
69
     *
70
     * @var array
71
     */
72
    protected $sessionData = [
73
        'sessionId' => null,
74
        'sequenceNumber' => null,
75
        'securityToken' => null
76
    ];
77
78
    /**
79
     * Status variable to know if the session is currently logged in
80
     *
81
     * @var bool
82
     */
83
    protected $isAuthenticated = false;
84
85
    /**
86
     * @var array[string]\SoapClient
87
     */
88
    protected $soapClients = [];
89
90
    /**
91
     * Default SoapClient options used during initialisation
92
     *
93
     * Can be overridden by providing custom options in
94
     * Amadeus\Client\Params\SessionHandlerParams::$soapClientOptions
95
     *
96
     * @var array
97
     */
98
    protected $soapClientOptions = [
99
        'trace' => 1,
100
        'exceptions' => 1,
101
        'soap_version' => SOAP_1_1
102
    ];
103
104
    /**
105
     * @var SessionHandlerParams
106
     */
107
    protected $params;
108
109
    /**
110
     * A map of which messages are available in the provided WSDL's
111
     *
112
     * format:
113
     * [
114
     *      'PNR_Retrieve' => [
115
     *          'version' => '14.1',
116
     *          'wsdl' => '7d36c7b8'
117
     *      ],
118
     *      'Media_GetMedia' => [
119
     *          'version' => '14.1',
120
     *          'wsdl' => '7e84f2537'
121
     *      ]
122
     * ]
123
     *
124
     * @var array
125
     */
126
    protected $messagesAndVersions = [];
127
128
    /**
129
     * Get the session parameters of the active session
130
     *
131
     * @return array|null
132
     */
133 3
    public function getSessionData()
134
    {
135 3
        return $this->sessionData;
136
    }
137
138
    /**
139
     * Set the session data to continue a previously started session.
140
     *
141
     * @param array $sessionData
142
     * @return bool
143
     */
144 3
    public function setSessionData(array $sessionData)
145
    {
146 3
        if (isset($sessionData['sessionId'], $sessionData['sequenceNumber'], $sessionData['securityToken'])) {
147 2
            $this->sessionData['sessionId'] = $sessionData['sessionId'];
148 2
            $this->sessionData['sequenceNumber'] = $sessionData['sequenceNumber'];
149 2
            $this->sessionData['securityToken'] = $sessionData['securityToken'];
150 2
            $this->isAuthenticated = true;
151 2
        } else {
152 1
            $this->isAuthenticated = false;
153
        }
154
155 3
        return $this->isAuthenticated;
156
    }
157
158
159
    /**
160
     * @param SessionHandlerParams $params
161
     */
162 52
    public function __construct(SessionHandlerParams $params)
163
    {
164 52
        $this->params = $params;
165 52
        if ($params->logger instanceof LoggerInterface) {
166 48
            $this->setLogger($params->logger);
167 48
            $this->log(LogLevel::INFO, __METHOD__."(): Logger started.");
168 48
        }
169 52
        if ($params->overrideSoapClient instanceof \SoapClient) {
170 10
            $this->soapClients[$params->overrideSoapClientWsdlName] = $params->overrideSoapClient;
171 10
        }
172 52
        $this->setStateful($params->stateful);
173 52
    }
174
175
176
    /**
177
     * @param string $messageName Method Operation name as defined in the WSDL.
178
     * @param BaseWsMessage $messageBody
179
     * @param array $messageOptions options: bool 'asString', bool 'endSession'
180
     * @return SendResult
181
     * @throws \InvalidArgumentException
182
     * @throws Client\Exception
183
     * @throws \SoapFault
184
     */
185 11
    public function sendMessage($messageName, Client\Struct\BaseWsMessage $messageBody, $messageOptions = [])
186
    {
187 11
        $result = new SendResult(
188 11
            $this->getActiveVersionFor($messageName)
189 11
        );
190
191 11
        $this->prepareForNextMessage($messageName, $messageOptions);
192
193
        try {
194 10
            $result->responseObject = $this->getSoapClient($messageName)->$messageName($messageBody);
195
196 8
            $this->logRequestAndResponse($messageName);
197
198 8
            $this->handlePostMessage($messageName, $this->getLastResponse($messageName), $messageOptions, $result);
199 10
        } catch (\SoapFault $ex) {
200 1
            $this->log(
201 1
                LogLevel::ERROR,
202 1
                "SOAPFAULT while sending message ".$messageName.": ".$ex->getMessage().
203 1
                " code: ".$ex->getCode()." at ".$ex->getFile()." line ".$ex->getLine().
204 1
                ": \n".$ex->getTraceAsString()
205 1
            );
206 1
            $this->logRequestAndResponse($messageName);
207 1
            $result->exception = $ex;
208 2
        } catch (\Exception $ex) {
209
            // We should only come here when the XSL extension is not enabled
210
            // or the XSLT transformation file is unreadable
211 1
            $this->log(
212 1
                LogLevel::ERROR,
213 1
                "EXCEPTION while sending message ".$messageName.": ".$ex->getMessage().
214 1
                " at ".$ex->getFile()." line ".$ex->getLine().": \n".$ex->getTraceAsString()
215 1
            );
216 1
            $this->logRequestAndResponse($messageName);
217 1
            throw new Client\Exception($ex->getMessage(), $ex->getCode(), $ex);
218
        }
219
220 9
        $result->responseXml = Client\Util\MsgBodyExtractor::extract($this->getLastResponse($messageName));
221
222 9
        return $result;
223
    }
224
225
    /**
226
     * Prepare to send a next message and checks if authenticated
227
     *
228
     * @param string $messageName
229
     * @param array $messageOptions
230
     */
231
    abstract protected function prepareForNextMessage($messageName, $messageOptions);
232
233
    /**
234
     * Handles post message actions
235
     *
236
     * Handles session state based on received response
237
     *
238
     * @param string $messageName
239
     * @param string $lastResponse
240
     * @param array $messageOptions
241
     * @param mixed $result
242
     */
243
    abstract protected function handlePostMessage($messageName, $lastResponse, $messageOptions, $result);
244
245
    /**
246
     * Get the last raw XML message that was sent out
247
     *
248
     * @param string $msgName
249
     * @return string|null
250
     */
251 3
    public function getLastRequest($msgName)
252
    {
253 3
        return $this->executeMethodOnSoapClientForMsg(
254 3
            $msgName,
255
            '__getLastRequest'
256 3
        );
257
    }
258
259
    /**
260
     * Get the last raw XML message that was received
261
     *
262
     * @param string $msgName
263
     * @return string|null
264
     */
265 10
    public function getLastResponse($msgName)
266
    {
267 10
        return $this->executeMethodOnSoapClientForMsg(
268 10
            $msgName,
269
            '__getLastResponse'
270 10
        );
271
    }
272
273
    /**
274
     * Get the request headers for the last SOAP message that was sent out
275
     *
276
     * @param string $msgName
277
     * @return string|null
278
     */
279 2
    public function getLastRequestHeaders($msgName)
280
    {
281 2
        return $this->executeMethodOnSoapClientForMsg(
282 2
            $msgName,
283
            '__getLastRequestHeaders'
284 2
        );
285
    }
286
287
    /**
288
     * Get the response headers for the last SOAP message that was received
289
     *
290
     * @param string $msgName
291
     * @return string|null
292
     */
293 2
    public function getLastResponseHeaders($msgName)
294
    {
295 2
        return $this->executeMethodOnSoapClientForMsg(
296 2
            $msgName,
297
            '__getLastResponseHeaders'
298 2
        );
299
    }
300
301
    /**
302
     * Get the office that we are using to sign in to.
303
     *
304
     * @return string
305
     */
306 12
    public function getOriginatorOffice()
307
    {
308 12
        return $this->params->authParams->officeId;
309
    }
310
311
312
    /**
313
     * Extract the Messages and versions from the loaded WSDL file.
314
     *
315
     * Result is an associative array: keys are message names, values are versions.
316
     *
317
     * @return array
318
     */
319 31
    public function getMessagesAndVersions()
320
    {
321 31
        if (empty($this->messagesAndVersions)) {
322 31
            $this->messagesAndVersions = $this->loadMessagesAndVersions();
323 29
        }
324
325 29
        return $this->messagesAndVersions;
326
    }
327
328
    /**
329
     * Loads messages & versions from WSDL.
330
     *
331
     * @return array
332
     */
333 31
    protected function loadMessagesAndVersions()
334
    {
335 31
        return WsdlAnalyser::loadMessagesAndVersions(
336 31
            $this->params->wsdl
337 31
        );
338
    }
339
340
    /**
341
     * Get the version number active in the WSDL for the given message
342
     *
343
     * @param $messageName
344
     * @return float|string|null
345
     */
346 11
    protected function getActiveVersionFor($messageName)
347
    {
348 11
        $msgAndVer = $this->getMessagesAndVersions();
349
350 11
        $found = null;
351
352 11
        if (isset($msgAndVer[$messageName]) && isset($msgAndVer[$messageName]['version'])) {
353 11
            $found = $msgAndVer[$messageName]['version'];
354 11
        }
355
356 11
        return $found;
357
    }
358
359
    /**
360
     * Get the WSDL ID for the given message
361
     *
362
     * @param $messageName
363
     * @return string|null
364
     */
365 17
    protected function getWsdlIdFor($messageName)
366
    {
367 17
        $msgAndVer = $this->getMessagesAndVersions();
368
369 17
        if (isset($msgAndVer[$messageName]) && isset($msgAndVer[$messageName]['wsdl'])) {
370 15
            return $msgAndVer[$messageName]['wsdl'];
371
        }
372
373 2
        return null;
374
    }
375
376
377
    /**
378
     * @param string $msgName
379
     * @return \SoapClient
380
     */
381 14
    protected function getSoapClient($msgName)
382
    {
383 14
        $wsdlId = $this->getWsdlIdFor($msgName);
384
385 14
        if (!empty($msgName)) {
386 12
            if (!isset($this->soapClients[$wsdlId]) || !($this->soapClients[$wsdlId] instanceof \SoapClient)) {
387 2
                $this->soapClients[$wsdlId] = $this->initSoapClient($wsdlId);
388 2
            }
389
390 12
            return $this->soapClients[$wsdlId];
391
        } else {
392 2
            return null;
393
        }
394
    }
395
396
    /**
397
     * @param string $wsdlId
398
     * @return \SoapClient
399
     */
400 2
    protected function initSoapClient($wsdlId)
401
    {
402 2
        $wsdlPath = WsdlAnalyser::$wsdlIds[$wsdlId];
403
404 2
        $client = new Client\SoapClient(
405 2
            $wsdlPath,
406 2
            $this->makeSoapClientOptions(),
407 2
            $this->params->logger
408 2
        );
409
410 2
        return $client;
411
    }
412
413
    /**
414
     * Make Soap Header specific SoapClient options
415
     *
416
     * @return array
417
     */
418
    abstract protected function makeSoapClientOptions();
419
420
    /**
421
     * @param string $msgName
422
     * @param string $method
423
     * @return null|string
424
     */
425 13
    protected function executeMethodOnSoapClientForMsg($msgName, $method)
426
    {
427 13
        $result = null;
428 13
        $soapClient = $this->getSoapClient($msgName);
429
430 13
        if ($soapClient instanceof \SoapClient) {
431 11
            $result = $soapClient->$method();
432 11
        }
433
434 13
        return $result;
435
    }
436
437
    /**
438
     * @param string $messageName
439
     * @uses $this->log
440
     */
441 10
    protected function logRequestAndResponse($messageName)
442
    {
443 10
        $this->log(
444 10
            LogLevel::INFO,
445 10
            'Called '.$messageName.' with request: '.$this->getSoapClient($messageName)->__getLastRequest()
446 10
        );
447 10
        $this->log(
448 10
            LogLevel::INFO,
449 10
            'Response:  '.$this->getSoapClient($messageName)->__getLastResponse()
450 10
        );
451 10
    }
452
453
    /**
454
     * @param mixed $level
455
     * @param string $message
456
     * @param array $context
457
     * @return null
458
     */
459 51
    protected function log($level, $message, $context = [])
460
    {
461 51
        if (is_null($this->logger)) {
462 3
            $this->setLogger(new NullLogger());
463 3
        }
464
465 51
        return $this->logger->log($level, $message, $context);
466
    }
467
}
468