Ratepay   B
last analyzed

Complexity

Total Complexity 43

Size/Duplication

Total Lines 363
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 96
c 2
b 0
f 0
dl 0
loc 363
rs 8.96
wmc 43

17 Methods

Rating   Name   Duplication   Size   Complexity  
A getRatepayShopConfigByPaymentMethod() 0 3 1
A __construct() 0 17 1
A getPaymentMethodFromPath() 0 7 3
A getRatepayShopConfigByPath() 0 16 5
A importProfileConfiguration() 0 8 4
A getRatepayShopConfigIdsByPaymentMethod() 0 12 3
A getShopConfigProperty() 0 8 2
A refreshProfiles() 0 12 5
A getRatepaySingleConfig() 0 13 3
A getRatepayConfig() 0 12 3
A getShopConfigByQuote() 0 11 3
A generateDeviceFingerprintToken() 0 3 1
A getShopIdByQuote() 0 10 2
A getRatepayShopConfigById() 0 7 2
A getRatepayDeviceFingerprintToken() 0 8 2
A getRatepayMethodIdentifierByMethodCode() 0 6 2
A getRatepayShopId() 0 6 1

How to fix   Complexity   

Complex Class

Complex classes like Ratepay often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Ratepay, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * PAYONE Magento 2 Connector is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU Lesser General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * PAYONE Magento 2 Connector is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public License
15
 * along with PAYONE Magento 2 Connector. If not, see <http://www.gnu.org/licenses/>.
16
 *
17
 * PHP version 5
18
 *
19
 * @category  Payone
20
 * @package   Payone_Magento2_Plugin
21
 * @author    FATCHIP GmbH <[email protected]>
22
 * @copyright 2003 - 2020 Payone GmbH
23
 * @license   <http://www.gnu.org/licenses/> GNU Lesser General Public License
24
 * @link      http://www.payone.de
25
 */
26
27
namespace Payone\Core\Helper;
28
29
use Payone\Core\Model\PayoneConfig;
30
31
/**
32
 * Helper class for ratepay payment
33
 */
34
class Ratepay extends \Payone\Core\Helper\Base
35
{
36
    /**
37
     * Map for methodCode to short payment method identifier for database columns
38
     *
39
     * @var array
40
     */
41
    protected $aMethodIdentifierMap = [
42
        PayoneConfig::METHOD_RATEPAY_INVOICE => 'invoice',
43
        PayoneConfig::METHOD_RATEPAY_DEBIT => 'elv',
44
        PayoneConfig::METHOD_RATEPAY_INSTALLMENT => 'installment',
45
    ];
46
47
    /**
48
     * Object of profile request
49
     *
50
     * @var \Payone\Core\Model\Api\Request\Genericpayment\Profile
51
     */
52
    protected $profile;
53
54
    /**
55
     * Ratepay profile resource model
56
     *
57
     * @var \Payone\Core\Model\ResourceModel\RatepayProfileConfig
58
     */
59
    protected $profileResource;
60
61
    /**
62
     * Checkout session
63
     *
64
     * @var \Magento\Checkout\Model\Session
0 ignored issues
show
Bug introduced by
The type Magento\Checkout\Model\Session was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
65
     */
66
    protected $checkoutSession;
67
68
    /**
69
     * Payone API helper
70
     *
71
     * @var \Payone\Core\Helper\Api
72
     */
73
    protected $apiHelper;
74
75
    /**
76
     * Payone Payment helper
77
     *
78
     * @var \Payone\Core\Helper\Payment
79
     */
80
    protected $paymentHelper;
81
82
    /**
83
     * Constructor
84
     *
85
     * @param \Magento\Framework\App\Helper\Context                 $context
86
     * @param \Magento\Store\Model\StoreManagerInterface            $storeManager
87
     * @param \Payone\Core\Helper\Shop                              $shopHelper
88
     * @param \Magento\Framework\App\State                          $state
89
     * @param \Payone\Core\Model\Api\Request\Genericpayment\Profile $profile
90
     * @param \Payone\Core\Model\ResourceModel\RatepayProfileConfig $profileResource
91
     * @param \Magento\Checkout\Model\Session                       $checkoutSession
92
     * @param \Payone\Core\Helper\Api                               $apiHelper
93
     * @param \Payone\Core\Helper\Payment                           $paymentHelper
94
     */
95
    public function __construct(
96
        \Magento\Framework\App\Helper\Context $context,
0 ignored issues
show
Bug introduced by
The type Magento\Framework\App\Helper\Context was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
97
        \Magento\Store\Model\StoreManagerInterface $storeManager,
0 ignored issues
show
Bug introduced by
The type Magento\Store\Model\StoreManagerInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
98
        \Payone\Core\Helper\Shop $shopHelper,
99
        \Magento\Framework\App\State $state,
0 ignored issues
show
Bug introduced by
The type Magento\Framework\App\State was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
100
        \Payone\Core\Model\Api\Request\Genericpayment\Profile $profile,
101
        \Payone\Core\Model\ResourceModel\RatepayProfileConfig $profileResource,
102
        \Magento\Checkout\Model\Session $checkoutSession,
103
        \Payone\Core\Helper\Api $apiHelper,
104
        \Payone\Core\Helper\Payment $paymentHelper
105
    ) {
106
        parent::__construct($context, $storeManager, $shopHelper, $state);
107
        $this->profile = $profile;
108
        $this->profileResource = $profileResource;
109
        $this->checkoutSession = $checkoutSession;
110
        $this->apiHelper = $apiHelper;
111
        $this->paymentHelper = $paymentHelper;
112
    }
113
114
    /**
115
     * Returns json decoded array with ratepay shop config by given payment method
116
     *
117
     * @param  string $sPaymentMethod
118
     * @return array
119
     */
120
    public function getRatepayShopConfigByPaymentMethod($sPaymentMethod)
121
    {
122
        return $this->getRatepayShopConfigByPath("payone_payment/".$sPaymentMethod."/ratepay_shop_config");
123
    }
124
125
    /**
126
     * Extract shop_ids from configured shop ids for given payment method
127
     *
128
     * @param  string $sPaymentMethod
129
     * @return array
130
     */
131
    public function getRatepayShopConfigIdsByPaymentMethod($sPaymentMethod)
132
    {
133
        $aShopConfig = $this->getRatepayShopConfigByPaymentMethod($sPaymentMethod);
134
135
        $aShopIds = [];
136
        foreach ($aShopConfig as $aConfig) {
137
            if (!empty($aConfig['shop_id'])) {
138
                $aShopIds[] = $aConfig['shop_id'];
139
            }
140
        }
141
142
        return $aShopIds;
143
    }
144
145
    /**
146
     * Returns json decoded array with ratepay shop config id by full config path
147
     *
148
     * @param  string $sPath
149
     * @return array
150
     */
151
    public function getRatepayShopConfigByPath($sPath)
152
    {
153
        $aReturn = [];
154
155
        $sShopConfig = $this->getConfigParamByPath($sPath);
156
        if (!empty($sShopConfig)) {
157
            $aShopConfig = json_decode($sShopConfig, true);
158
            if (is_array($aShopConfig)) {
159
                foreach ($aShopConfig as $aConfig) {
160
                    if (!empty($aConfig['shop_id'])) {
161
                        $aReturn[] = $aConfig;
162
                    }
163
                }
164
            }
165
        }
166
        return $aReturn;
167
    }
168
169
    /**
170
     * Extract payment method from config path
171
     *
172
     * @param  string $sPath
173
     * @return bool|mixed
174
     */
175
    public function getPaymentMethodFromPath($sPath)
176
    {
177
        preg_match("/payone_payment\/(.*)\/ratepay_shop_config/", $sPath, $aMatch);
178
        if (is_array($aMatch) && isset($aMatch[1])) {
179
            return $aMatch[1];
180
        }
181
        return false;
182
    }
183
184
    /**
185
     * Imports new profile configuration
186
     *
187
     * @param  string $sShopId
188
     * @param  string $sCurrency
189
     * @param  string $sMethodCode
190
     * @return void
191
     */
192
    public function importProfileConfiguration($sShopId, $sCurrency, $sMethodCode)
193
    {
194
        if ($this->profileResource->profileExists($sShopId) === false) {
195
            $sMode = $this->getConfigParam('mode', $sMethodCode, 'payone_payment');
196
            $aResult = $this->profile->sendRequest($sShopId, $sCurrency, $sMode);
197
            if (isset($aResult['status'])) {
198
                if ($aResult['status'] == 'OK') {
199
                    $this->profileResource->insertProfileConfig($sShopId, $aResult);
200
                }
201
            }
202
        }
203
    }
204
205
    /**
206
     * Refreshes all of the profile configs of the given payment method
207
     *
208
     * @param  $sMethodCode
209
     * @return void
210
     */
211
    public function refreshProfiles($sMethodCode)
212
    {
213
        $sMode = $this->getConfigParam('mode', $sMethodCode, 'payone_payment');
214
215
        $aShopIds = $this->getRatepayShopConfigByPaymentMethod($sMethodCode);
216
        foreach ($aShopIds as $aConfig) {
217
            $aResult = $this->profile->sendRequest($aConfig['shop_id'], $aConfig['currency'], $sMode);
218
            if (!isset($aResult['status']) || $aResult['status'] != 'OK') {
219
                throw new \Exception("An error occured".(!empty($aResult['errormessage']) ? ": ".$aResult['errormessage'] : ""));
220
            }
221
222
            $this->profileResource->updateProfileConfig($aConfig['shop_id'], $aResult);
223
        }
224
    }
225
226
    /**
227
     * Generates device fingerprint token vom customer id and time
228
     *
229
     * @return string
230
     */
231
    protected function generateDeviceFingerprintToken()
232
    {
233
        return md5($this->checkoutSession->getQuote()->getCustomer()->getId().'_'.microtime());
234
    }
235
236
    /**
237
     * Generates Ratepay device fingerprint token or takes it from the checkout session
238
     *
239
     * @return string
240
     */
241
    public function getRatepayDeviceFingerprintToken()
242
    {
243
        $sTokenFromSession = $this->checkoutSession->getPayoneRatepayDeviceFingerprintToken();
244
        if (empty($sTokenFromSession)) {
245
            $sTokenFromSession = $this->generateDeviceFingerprintToken();
246
            $this->checkoutSession->setPayoneRatepayDeviceFingerprintToken($sTokenFromSession);
247
        }
248
        return $sTokenFromSession;
249
    }
250
251
    /**
252
     * Returns ratepay method identifier
253
     *
254
     * @param  string $sMethodCode
255
     * @return string|false
256
     */
257
    protected function getRatepayMethodIdentifierByMethodCode($sMethodCode)
258
    {
259
        if (isset($this->aMethodIdentifierMap[$sMethodCode])) {
260
            return $this->aMethodIdentifierMap[$sMethodCode];
261
        }
262
        return false;
263
    }
264
265
    /**
266
     * Get matching Ratepay shop id for current transaction
267
     *
268
     * @param  string $sMethodCode
269
     * @param  string $sCountryCode
270
     * @param  string $sCurrency
271
     * @param  double $dGrandTotal
272
     * @param  bool $blGetConfigWithoutTotals
273
     * @return string|false
274
     */
275
    public function getRatepayShopId($sMethodCode, $sCountryCode, $sCurrency, $dGrandTotal, $blGetConfigWithoutTotals = false)
276
    {
277
        $sRatepayMethodIdentifier = $this->getRatepayMethodIdentifierByMethodCode($sMethodCode);
278
279
        $aShopIds = $this->getRatepayShopConfigIdsByPaymentMethod($sMethodCode);
280
        return $this->profileResource->getMatchingShopId($sRatepayMethodIdentifier, $aShopIds, $sCountryCode, $sCurrency, $dGrandTotal, $blGetConfigWithoutTotals);
281
    }
282
283
    /**
284
     * Returns matching Ratepay shop id by given quote
285
     *
286
     * @param  string $sMethodCode
287
     * @param  \Magento\Quote\Api\Data\CartInterface $quote
288
     * @param  bool $blGetConfigWithoutTotals
289
     * @return string
290
     * @throws \Magento\Framework\Exception\LocalizedException
291
     */
292
    public function getShopIdByQuote($sMethodCode, \Magento\Quote\Api\Data\CartInterface $quote, $blGetConfigWithoutTotals = false)
0 ignored issues
show
Bug introduced by
The type Magento\Quote\Api\Data\CartInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
293
    {
294
        $sCountryCode = $quote->getShippingAddress()->getCountryId();
295
        if (empty($sCountryCode)) {
296
            $sCountryCode = $quote->getBillingAddress()->getCountryId();
297
        }
298
        $sCurrency = $this->apiHelper->getCurrencyFromQuote($quote);
299
        $dGrandTotal = $this->apiHelper->getQuoteAmount($quote);
300
301
        return $this->getRatepayShopId($sMethodCode, $sCountryCode, $sCurrency, $dGrandTotal, $blGetConfigWithoutTotals);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getRatepay...GetConfigWithoutTotals) could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
302
    }
303
304
    /**
305
     * Returns matching Ratepay shop config by quote
306
     *
307
     * @param  string $sMethodCode
308
     * @param  \Magento\Quote\Api\Data\CartInterface|null $quote
309
     * @param  bool $blGetConfigWithoutTotals
310
     * @return array
311
     */
312
    public function getShopConfigByQuote($sMethodCode, ?\Magento\Quote\Api\Data\CartInterface $quote = null, $blGetConfigWithoutTotals = false)
313
    {
314
        if ($quote === null) {
315
            $quote = $this->checkoutSession->getQuote();
316
        }
317
318
        $sShopId = $this->getShopIdByQuote($sMethodCode, $quote, $blGetConfigWithoutTotals);
319
        if (empty($sShopId)) {
320
            return [];
321
        }
322
        return $this->getRatepayShopConfigById($sShopId);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getRatepayShopConfigById($sShopId) could also return false which is incompatible with the documented return type array. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
323
    }
324
325
    /**
326
     * Returns a certain property from the given shop config array
327
     *
328
     * @param  array $aShopConfig
329
     * @param  string $sMethodCode
330
     * @param  string $sProperty
331
     * @return string|false
332
     */
333
    public function getShopConfigProperty($aShopConfig, $sMethodCode, $sProperty)
334
    {
335
        $sRatepayMethodIdentifier = $this->getRatepayMethodIdentifierByMethodCode($sMethodCode);
336
337
        if (isset($aShopConfig[$sProperty.'_'.$sRatepayMethodIdentifier])) {
0 ignored issues
show
Bug introduced by
Are you sure $sRatepayMethodIdentifier of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

337
        if (isset($aShopConfig[$sProperty.'_'./** @scrutinizer ignore-type */ $sRatepayMethodIdentifier])) {
Loading history...
338
            return $aShopConfig[$sProperty.'_'.$sRatepayMethodIdentifier];
339
        }
340
        return false;
341
    }
342
343
    /**
344
     * Get matching Ratepay shop config for current transaction
345
     *
346
     * @param string $sShopId
347
     * @return array|false
348
     */
349
    public function getRatepayShopConfigById($sShopId)
350
    {
351
        $aProfileConfigs = $this->profileResource->getProfileConfigsByIds([$sShopId]);
352
        if (!empty($aProfileConfigs)) {
353
            return array_shift($aProfileConfigs);
354
        }
355
        return false;
356
    }
357
358
    /**
359
     * Return Ratepay config for config provider
360
     *
361
     * @return array
362
     */
363
    public function getRatepayConfig()
364
    {
365
        $aReturn = [];
366
367
        foreach (PayoneConfig::METHODS_RATEPAY as $sRatepayMethod) {
368
            if ($this->paymentHelper->isPaymentMethodActive($sRatepayMethod) === true) {
369
                $aReturn[$sRatepayMethod] = $this->getRatepaySingleConfig($sRatepayMethod);
370
            }
371
        }
372
        $aReturn['snippetId'] = $this->getConfigParam('devicefingerprint_snippet_id', 'ratepay', 'payone_misc');
373
        $aReturn['token'] = $this->getRatepayDeviceFingerprintToken();
374
        return $aReturn;
375
    }
376
377
    /**
378
     * Return Ratepay configuration for given method code
379
     *
380
     * @param  string $sRatepayMethodCode
381
     * @param  \Magento\Quote\Api\Data\CartInterface|null $quote
382
     * @return array|bool[]
383
     */
384
    public function getRatepaySingleConfig($sRatepayMethodCode, ?\Magento\Quote\Api\Data\CartInterface $quote = null)
385
    {
386
        $aShopConfig = $this->getShopConfigByQuote($sRatepayMethodCode, $quote);
387
        if (empty($aShopConfig)) {
388
            $aShopConfig = $this->getShopConfigByQuote($sRatepayMethodCode, $quote, true);
389
            if (empty($aShopConfig)) {
390
                return [];
391
            }
392
        }
393
394
        return [
395
            'b2bAllowed' => (bool)$this->getShopConfigProperty($aShopConfig, $sRatepayMethodCode, 'b2b'),
396
            'differentAddressAllowed' => (bool)$this->getShopConfigProperty($aShopConfig, $sRatepayMethodCode, 'delivery_address'),
397
        ];
398
    }
399
}
400