CheckoutSubmitBefore   B
last analyzed

Complexity

Total Complexity 43

Size/Duplication

Total Lines 272
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 89
dl 0
loc 272
rs 8.96
c 1
b 0
f 0
wmc 43

11 Methods

Rating   Name   Duplication   Size   Complexity  
B getScoreByCreditrating() 0 27 8
A __construct() 0 12 1
A getConfigParam() 0 7 2
A getPaymentWhitelist() 0 7 2
B isPaymentApplicableForScore() 0 18 7
A isBonicheckAgreementActiveAndNotConfirmedByCustomer() 0 9 4
A getInsufficientScoreMessage() 0 7 2
A isPaymentMethodEnabledForCheck() 0 7 2
A checkoutNeedsToBeStopped() 0 7 5
A isCreditratingNeeded() 0 15 4
A execute() 0 31 6

How to fix   Complexity   

Complex Class

Complex classes like CheckoutSubmitBefore 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 CheckoutSubmitBefore, 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 - 2016 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\Observer;
28
29
use Magento\Framework\Event\ObserverInterface;
0 ignored issues
show
Bug introduced by
The type Magento\Framework\Event\ObserverInterface 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...
30
use Magento\Framework\Event\Observer;
0 ignored issues
show
Bug introduced by
The type Magento\Framework\Event\Observer 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...
31
use Magento\Framework\Exception\LocalizedException;
0 ignored issues
show
Bug introduced by
The type Magento\Framework\Exception\LocalizedException 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...
32
use Magento\Quote\Model\Quote;
0 ignored issues
show
Bug introduced by
The type Magento\Quote\Model\Quote 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...
33
use Magento\Quote\Api\Data\AddressInterface;
0 ignored issues
show
Bug introduced by
The type Magento\Quote\Api\Data\AddressInterface 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...
34
use Payone\Core\Model\Source\CreditratingIntegrationEvent as Event;
35
use Payone\Core\Model\Source\PersonStatus;
36
use Payone\Core\Model\Exception\FilterMethodListException;
37
38
/**
39
 * Event class to set the orderstatus to new and pending
40
 */
41
class CheckoutSubmitBefore implements ObserverInterface
42
{
43
    /**
44
     * PAYONE consumerscore request model
45
     *
46
     * @var \Payone\Core\Model\Api\Request\Consumerscore
47
     */
48
    protected $consumerscore;
49
50
    /**
51
     * Consumerscore helper
52
     *
53
     * @var \Payone\Core\Helper\Consumerscore
54
     */
55
    protected $consumerscoreHelper;
56
57
    /**
58
     * Addresscheck management object
59
     *
60
     * @var \Payone\Core\Model\Risk\Addresscheck
61
     */
62
    protected $addresscheck;
63
64
    /**
65
     * Checkout session object
66
     *
67
     * @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...
68
     */
69
    protected $checkoutSession;
70
71
    /**
72
     * Payone customer helper
73
     *
74
     * @var \Payone\Core\Helper\Customer
75
     */
76
    protected $customerHelper;
77
78
    /**
79
     * Constructor
80
     *
81
     * @param \Payone\Core\Model\Api\Request\Consumerscore $consumerscore
82
     * @param \Payone\Core\Helper\Consumerscore            $consumerscoreHelper
83
     * @param \Payone\Core\Model\Risk\Addresscheck         $addresscheck
84
     * @param \Magento\Checkout\Model\Session              $checkoutSession
85
     * @param \Payone\Core\Helper\Customer                 $customerHelper
86
     */
87
    public function __construct(
88
        \Payone\Core\Model\Api\Request\Consumerscore $consumerscore,
89
        \Payone\Core\Helper\Consumerscore $consumerscoreHelper,
90
        \Payone\Core\Model\Risk\Addresscheck $addresscheck,
91
        \Magento\Checkout\Model\Session $checkoutSession,
92
        \Payone\Core\Helper\Customer $customerHelper
93
    ) {
94
        $this->consumerscore = $consumerscore;
95
        $this->consumerscoreHelper = $consumerscoreHelper;
96
        $this->addresscheck = $addresscheck;
97
        $this->checkoutSession = $checkoutSession;
98
        $this->customerHelper = $customerHelper;
99
    }
100
101
    /**
102
     * Get parameter from config
103
     *
104
     * @param  string $sParam
105
     * @param  bool   $blIsAddresscheck
106
     * @return string
107
     */
108
    public function getConfigParam($sParam, $blIsAddresscheck = false)
109
    {
110
        $sGroup = 'creditrating';
111
        if ($blIsAddresscheck === true) {
112
            $sGroup = 'address_check';
113
        }
114
        return $this->consumerscoreHelper->getConfigParam($sParam, $sGroup, 'payone_protect');
115
    }
116
117
    /**
118
     * Check if given payment methods was enabled for bonicheck in the configuration
119
     *
120
     * @param  string $sPaymentCode
121
     * @return bool
122
     */
123
    protected function isPaymentMethodEnabledForCheck($sPaymentCode)
124
    {
125
        $aPaymentTypesToCheck = $this->consumerscoreHelper->getConsumerscoreEnabledMethods();
126
        if (array_search($sPaymentCode, $aPaymentTypesToCheck) !== false) {
127
            return true;
128
        }
129
        return false;
130
    }
131
132
    /**
133
     * Determine if creditrating is needed
134
     *
135
     * @param  Quote $oQuote
136
     * @return bool
137
     */
138
    public function isCreditratingNeeded(Quote $oQuote)
139
    {
140
        if (!$this->consumerscoreHelper->isCreditratingNeeded(Event::AFTER_PAYMENT, $oQuote->getGrandTotal())) {
141
            return false;
142
        }
143
144
        if ($this->isPaymentMethodEnabledForCheck($oQuote->getPayment()->getMethodInstance()->getCode()) === false) {
145
            return false;
146
        }
147
148
        if ($oQuote->getPayment()->getMethodInstance()->getInfoInstance()->getAdditionalInformation('payone_boni_agreement') === false) { // getAdditionalInformation() returns null if field not existing
149
            return false; // agreement checkbox was not checked by the customer
150
        }
151
152
        return true;
153
    }
154
155
    /**
156
     * @param Quote $oQuote
157
     */
158
    protected function isBonicheckAgreementActiveAndNotConfirmedByCustomer($oQuote)
159
    {
160
        if (!$this->consumerscoreHelper->canShowAgreementMessage() || // check if agreement is configured
161
            !$this->isPaymentMethodEnabledForCheck($oQuote->getPayment()->getMethodInstance()->getCode()) || // check if selected payment methods is enabled for bonicheck
162
            $oQuote->getPayment()->getMethodInstance()->getInfoInstance()->getAdditionalInformation('payone_boni_agreement') !== false // check if agreement was not confirmed
163
        ) {
164
            return false;
165
        }
166
        return true;
167
    }
168
169
    /**
170
     * Determine if the payment type can be used with this score
171
     *
172
     * @param  Quote $oQuote
173
     * @param  string $sScore
174
     * @return bool
175
     */
176
    public function isPaymentApplicableForScore(Quote $oQuote, $sScore)
177
    {
178
        if ($sScore == 'G') {
179
            return true;
180
        }
181
182
        $sPaymentCode = $oQuote->getPayment()->getMethodInstance()->getCode();
183
184
        $aYellowMethods = $this->consumerscoreHelper->getAllowedMethodsForScore('Y');
185
        $aRedMethods = $this->consumerscoreHelper->getAllowedMethodsForScore('R');
186
187
        if ($sScore == 'Y' && (array_search($sPaymentCode, $aYellowMethods) !== false ||
188
                array_search($sPaymentCode, $aRedMethods) !== false)) {
189
            return true;
190
        } elseif ($sScore == 'R' && array_search($sPaymentCode, $aRedMethods) !== false) {
191
            return true;
192
        }
193
        return false;
194
    }
195
196
    /**
197
     *
198
     * @param  array $aResponse
199
     * @return bool
200
     */
201
    public function checkoutNeedsToBeStopped($aResponse)
202
    {
203
        if (!$aResponse || (isset($aResponse['status']) && $aResponse['status'] == 'ERROR'
0 ignored issues
show
Bug Best Practice introduced by
The expression $aResponse of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
204
                && $this->getConfigParam('handle_response_error') == 'stop_checkout')) {
205
            return true;
206
        }
207
        return false;
208
    }
209
210
    /**
211
     * Filter payment methods by the creditrating result if applicable
212
     *
213
     * @param  AddressInterface $oBilling
214
     * @return string
215
     * @throws LocalizedException
216
     */
217
    public function getScoreByCreditrating(AddressInterface $oBilling)
218
    {
219
        $aResponse = $this->consumerscore->sendRequest($oBilling, $this->customerHelper->getCustomerGender(), $this->customerHelper->getCustomerBirthday());
220
        if ($aResponse === true) { // creditrating not executed because of a previous check
221
            $this->consumerscoreHelper->copyOldStatusToNewAddress($oBilling);
222
        }
223
224
        if ($this->checkoutNeedsToBeStopped($aResponse)) {
0 ignored issues
show
Bug introduced by
It seems like $aResponse can also be of type boolean; however, parameter $aResponse of Payone\Core\Observer\Che...ckoutNeedsToBeStopped() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

224
        if ($this->checkoutNeedsToBeStopped(/** @scrutinizer ignore-type */ $aResponse)) {
Loading history...
225
            $sErrorMsg = $this->getConfigParam('stop_checkout_message');
226
            if (empty($sErrorMsg)) {
227
                $sErrorMsg = 'An error occured during the credit check.';
228
            }
229
            throw new LocalizedException(__($sErrorMsg));
0 ignored issues
show
Bug introduced by
The function __ was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

229
            throw new LocalizedException(/** @scrutinizer ignore-call */ __($sErrorMsg));
Loading history...
230
        }
231
232
        if (isset($aResponse['score'])) {
233
            $oBilling->setPayoneProtectScore($aResponse['score'])->save();
234
        }
235
236
        $sScore = $oBilling->getPayoneProtectScore();
237
        if (isset($aResponse['personstatus']) && $aResponse['personstatus'] !== PersonStatus::NONE) {
238
            $aMapping = $this->addresscheck->getPersonstatusMapping();
239
            if (array_key_exists($aResponse['personstatus'], $aMapping)) {
240
                $sScore = $this->consumerscoreHelper->getWorstScore([$sScore, $aMapping[$aResponse['personstatus']]]);
241
            }
242
        }
243
        return $sScore;
244
    }
245
246
    /**
247
     * Get error message for when the creditrating failed because the score is insufficient
248
     *
249
     * @return string
250
     */
251
    public function getInsufficientScoreMessage()
252
    {
253
        $sErrorMsg = $this->getConfigParam('insufficient_score_message');
254
        if (empty($sErrorMsg)) {
255
            $sErrorMsg = 'An error occured during the credit check.';
256
        }
257
        return $sErrorMsg;
258
    }
259
260
    /**
261
     * Returns allowed payment methods for the given score
262
     *
263
     * @param  string $sScore
264
     * @return array
265
     */
266
    protected function getPaymentWhitelist($sScore)
267
    {
268
        $aWhitelist = $this->consumerscoreHelper->getAllowedMethodsForScore('R');
269
        if ($sScore == "Y") {
270
            $aWhitelist = array_merge($aWhitelist, $this->consumerscoreHelper->getAllowedMethodsForScore('Y'));
271
        }
272
        return $aWhitelist;
273
    }
274
275
    /**
276
     * Execute certain tasks after the payment is placed and thus the order is placed
277
     *
278
     * @param  Observer $observer
279
     * @return void
280
     * @throws LocalizedException
281
     */
282
    public function execute(Observer $observer)
283
    {
284
        /** @var Quote $oQuote */
285
        $oQuote = $observer->getQuote();
286
        if (!$oQuote) {
0 ignored issues
show
introduced by
$oQuote is of type Magento\Quote\Model\Quote, thus it always evaluated to true.
Loading history...
287
            return;
288
        }
289
290
        $oBilling = $oQuote->getBillingAddress();
291
        $oShipping = $oQuote->getShippingAddress();
292
293
        $aScores = [];
294
        if ($this->getConfigParam('enabled', true)) { // is addresscheck active
295
            $aScores[] = $oBilling->getPayoneAddresscheckScore();
296
            $aScores[] = $oShipping->getPayoneAddresscheckScore();
297
        }
298
299
        if ($this->isCreditratingNeeded($oQuote) === true) {
300
            $aScores[] = $this->getScoreByCreditrating($oBilling);
301
        }
302
303
        if ($this->isBonicheckAgreementActiveAndNotConfirmedByCustomer($oQuote) === true) {
304
            $aScores[] = 'R';
305
        }
306
307
        $sScore = $this->consumerscoreHelper->getWorstScore($aScores);
308
        $blSuccess = $this->isPaymentApplicableForScore($oQuote, $sScore);
309
        if ($blSuccess === false) {
310
            $aWhitelist = $this->getPaymentWhitelist($sScore);
311
            $this->checkoutSession->setPayonePaymentWhitelist($aWhitelist);
312
            throw new FilterMethodListException(__($this->getInsufficientScoreMessage()), $aWhitelist);
0 ignored issues
show
Bug introduced by
The function __ was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

312
            throw new FilterMethodListException(/** @scrutinizer ignore-call */ __($this->getInsufficientScoreMessage()), $aWhitelist);
Loading history...
313
        }
314
    }
315
}
316