Dialog   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 362
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 13

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
dl 0
loc 362
c 0
b 0
f 0
wmc 22
lcom 1
cbo 13
ccs 0
cts 139
cp 0
rs 10

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A sendMessage() 0 30 4
A handleResponse() 0 13 3
A logMessage() 0 18 4
A getDialogId() 0 4 1
A getMessageNumber() 0 4 1
A getSystemId() 0 4 1
A getSupportedPinTanMechanisms() 0 4 1
A getHksalMaxVersion() 0 4 1
A getHkkazMaxVersion() 0 4 1
A getBankName() 0 4 1
A initDialog() 0 28 1
A syncDialog() 0 46 1
A endDialog() 0 26 1
1
<?php
2
namespace Fhp\Dialog;
3
4
use Fhp\Adapter\Exception\AdapterException;
5
use Fhp\Adapter\Exception\CurlException;
6
use Fhp\Connection;
7
use Fhp\Dialog\Exception\FailedRequestException;
8
use Fhp\Message\AbstractMessage;
9
use Fhp\Message\Message;
10
use Fhp\Response\Initialization;
11
use Fhp\Response\Response;
12
use Fhp\Segment\HKEND;
13
use Fhp\Segment\HKIDN;
14
use Fhp\Segment\HKSYN;
15
use Fhp\Segment\HKVVB;
16
use Psr\Log\LoggerInterface;
17
use Psr\Log\LogLevel;
18
19
/**
20
 * Class Dialog
21
 * @package Fhp\Dialog
22
 */
23
class Dialog
24
{
25
    const DEFAULT_COUNTRY_CODE = 280;
26
27
    /**
28
     * @var Connection
29
     */
30
    protected $connection;
31
32
    /**
33
     * @var LoggerInterface
34
     */
35
    protected $logger;
36
37
    /**
38
     * @var int
39
     */
40
    protected $messageNumber = 1;
41
42
    /**
43
     * @var int
44
     */
45
    protected $dialogId = 0;
46
47
    /**
48
     * @var int|string
49
     */
50
    protected $systemId = 0;
51
52
    /**
53
     * @var string
54
     */
55
    protected $bankCode;
56
57
    /**
58
     * @var string
59
     */
60
    protected $username;
61
62
    /**
63
     * @var string
64
     */
65
    protected $pin;
66
67
    /**
68
     * @var string
69
     */
70
    protected $bankName;
71
72
    /**
73
     * @var array
74
     */
75
    protected $supportedTanMechanisms = array();
76
77
    /**
78
     * @var int
79
     */
80
    protected $hksalVersion = 6;
81
82
    /**
83
     * @var int
84
     */
85
    protected $hkkazVersion = 6;
86
87
    /**
88
     * Dialog constructor.
89
     *
90
     * @param Connection $connection
91
     * @param string $bankCode
92
     * @param string $username
93
     * @param string $pin
94
     * @param string $systemId
95
     * @param LoggerInterface $logger
96
     */
97
    public function __construct(Connection $connection, $bankCode, $username, $pin, $systemId, LoggerInterface $logger)
98
    {
99
        $this->connection = $connection;
100
        $this->bankCode = $bankCode;
101
        $this->username = $username;
102
        $this->pin = $pin;
103
        $this->systemId = $systemId;
104
        $this->logger = $logger;
105
    }
106
107
    /**
108
     * @param AbstractMessage $message
109
     * @return Response
110
     * @throws AdapterException
111
     * @throws CurlException
112
     * @throws FailedRequestException
113
     */
114
    public function sendMessage(AbstractMessage $message)
115
    {
116
        try {
117
            $this->logger->info('Sending Message');
118
            $message->setMessageNumber($this->messageNumber);
119
            $message->setDialogId($this->dialogId);
120
121
            $result = $this->connection->send($message);
122
            $this->messageNumber++;
123
            $response = new Response($result);
124
125
            $this->handleResponse($response);
126
127
            if (!$response->isSuccess()) {
128
                $summary = $response->getMessageSummary();
129
                $ex = new FailedRequestException($summary);
130
                $this->logger->error($ex->getMessage());
131
                throw $ex;
132
            }
133
134
            return $response;
135
        } catch (AdapterException $e) {
136
            $this->logger->critical($e->getMessage());
137
            if ($e instanceof CurlException) {
138
                $this->logger->debug(print_r($e->getCurlInfo(), true));
139
            }
140
141
            throw $e;
142
        }
143
    }
144
145
    /**
146
     * @param Response $response
147
     */
148
    protected function handleResponse(Response $response)
149
    {
150
        $summary = $response->getMessageSummary();
151
        $segSum  = $response->getSegmentSummary();
152
153
        foreach ($summary as $code => $message) {
154
            $this->logMessage('HIRMG', $code, $message);
155
        }
156
157
        foreach ($segSum as $code => $message) {
158
            $this->logMessage('HIRMS', $code, $message);
159
        }
160
    }
161
162
    /**
163
     * @param string $type
164
     * @param string $code
165
     * @param $message
166
     */
167
    protected function logMessage($type, $code, $message)
168
    {
169
        switch (substr($code, 0, 1)) {
170
            case '0':
171
                $level = LogLevel::INFO;
172
                break;
173
            case "3":
174
                $level = LogLevel::WARNING;
175
                break;
176
            case "9":
177
                $level = LogLevel::ERROR;
178
                break;
179
            default:
180
                $level = LogLevel::INFO;
181
        }
182
183
        $this->logger->log($level, '[' . $type . '] ' . $message);
184
    }
185
186
    /**
187
     * Gets the dialog ID.
188
     *
189
     * @return integer
190
     */
191
    public function getDialogId()
192
    {
193
        return $this->dialogId;
194
    }
195
196
    /**
197
     * Gets the current message number.
198
     *
199
     * @return int
200
     */
201
    public function getMessageNumber()
202
    {
203
        return $this->messageNumber;
204
    }
205
206
    /**
207
     * Gets the system ID.
208
     *
209
     * @return int|string
210
     */
211
    public function getSystemId()
212
    {
213
        return $this->systemId;
214
    }
215
216
    /**
217
     * Gets all supported TAN mechanisms.
218
     *
219
     * @return array
220
     */
221
    public function getSupportedPinTanMechanisms()
222
    {
223
        return $this->supportedTanMechanisms;
224
    }
225
226
    /**
227
     * Gets the max possible HKSAL version.
228
     *
229
     * @return int
230
     */
231
    public function getHksalMaxVersion()
232
    {
233
        return $this->hksalVersion;
234
    }
235
236
    /**
237
     * Gets the max possible HKKAZ version.
238
     *
239
     * @return int
240
     */
241
    public function getHkkazMaxVersion()
242
    {
243
        return $this->hkkazVersion;
244
    }
245
246
    /**
247
     * Gets the bank name.
248
     *
249
     * @return string
250
     */
251
    public function getBankName()
252
    {
253
        return $this->bankName;
254
    }
255
256
    /**
257
     * Initializes a dialog.
258
     *
259
     * @return string|null
260
     * @throws AdapterException
261
     * @throws CurlException
262
     * @throws FailedRequestException
263
     * @throws \Exception
264
     */
265
    public function initDialog()
266
    {
267
        $this->logger->info('Initialize Dialog');
268
        $identification = new HKIDN(3, $this->bankCode, $this->username, $this->systemId);
269
        $prepare        = new HKVVB(4, HKVVB::DEFAULT_BPD_VERSION, HKVVB::DEFAULT_UPD_VERSION, HKVVB::LANG_DEFAULT);
270
271
        $message = new Message(
272
            $this->bankCode,
273
            $this->username,
274
            $this->pin,
275
            $this->systemId,
276
            0,
277
            1,
278
            array($identification, $prepare),
279
            array(AbstractMessage::OPT_PINTAN_MECH => $this->supportedTanMechanisms)
280
        );
281
282
        $this->logger->debug('Sending INIT message: ' . (string) $message);
283
284
        $response = $this->sendMessage($message)->rawResponse;
285
        $this->logger->debug('Got INIT response: ' . $response);
286
287
        $result = new Initialization($response);
288
        $this->dialogId = $result->getDialogId();
0 ignored issues
show
Documentation Bug introduced by
It seems like $result->getDialogId() can also be of type string. However, the property $dialogId is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
289
        $this->logger->info('Received dialog ID: ' . $this->dialogId);
290
291
        return $this->dialogId;
292
    }
293
294
    /**
295
     * Sends sync request.
296
     *
297
     * @return string
298
     * @throws AdapterException
299
     * @throws CurlException
300
     * @throws FailedRequestException
301
     * @throws \Exception
302
     */
303
    public function syncDialog()
304
    {
305
        $this->logger->info('Initialize SYNC');
306
        $this->messageNumber = 1;
307
        $this->systemId = 0;
308
        $this->dialogId = 0;
309
310
        $identification = new HKIDN(3, $this->bankCode, $this->username, 0);
311
        $prepare        = new HKVVB(4, HKVVB::DEFAULT_BPD_VERSION, HKVVB::DEFAULT_UPD_VERSION, HKVVB::LANG_DEFAULT);
312
        $sync           = new HKSYN(5);
313
314
        $syncMsg = new Message(
315
            $this->bankCode,
316
            $this->username,
317
            $this->pin,
318
            $this->systemId,
319
            $this->dialogId,
320
            $this->messageNumber,
321
            array($identification, $prepare, $sync)
322
        );
323
324
        $this->logger->debug('Sending SYNC message: ' . (string) $syncMsg);
325
        $response = $this->sendMessage($syncMsg);
326
327
        $this->logger->debug('Got SYNC response: ' . $response->rawResponse);
328
329
        // save BPD (Bank Parameter Daten)
330
        $this->systemId = $response->getSystemId();
331
        $this->dialogId = $response->getDialogId();
0 ignored issues
show
Documentation Bug introduced by
It seems like $response->getDialogId() can also be of type string. However, the property $dialogId is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
332
        $this->bankName = $response->getBankName();
333
334
        // max version for segment HKSAL (Saldo abfragen)
335
        $this->hksalVersion = $response->getHksalMaxVersion();
336
        $this->supportedTanMechanisms = $response->getSupportedTanMechanisms();
337
338
        // max version for segment HKKAZ (Kontoumsätze anfordern / Zeitraum)
339
        $this->hkkazVersion = $response->getHkkazMaxVersion();
340
341
        $this->logger->info('Received system id: ' . $response->getSystemId());
342
        $this->logger->info('Received dialog id: ' . $response->getDialogId());
343
        $this->logger->info('Supported TAN mechanisms: ' . implode(', ', $this->supportedTanMechanisms));
344
345
        $this->endDialog();
346
347
        return $response->rawResponse;
348
    }
349
350
    /**
351
     * Ends a previous started dialog.
352
     *
353
     * @return string
354
     * @throws AdapterException
355
     * @throws CurlException
356
     * @throws FailedRequestException
357
     */
358
    public function endDialog()
359
    {
360
        $this->logger->info('Initialize END dialog message');
361
362
        $endMsg = new Message(
363
            $this->bankCode,
364
            $this->username,
365
            $this->pin,
366
            $this->systemId,
367
            $this->dialogId,
368
            $this->messageNumber,
369
            array(
370
                new HKEND(3, $this->dialogId)
371
            )
372
        );
373
374
        $this->logger->debug('Sending END message: ' . (string) $endMsg);
375
        $response = $this->sendMessage($endMsg);
376
        $this->logger->debug('Got END response: ' . $response->rawResponse);
377
378
        $this->logger->info('Resetting dialog ID and message number count');
379
        $this->dialogId = 0;
380
        $this->messageNumber = 1;
381
382
        return $response->rawResponse;
383
    }
384
}
385