Passed
Push — master ( 54a344...83c53d )
by Mario
03:09
created

Bootstrap   F

Complexity

Total Complexity 358

Size/Duplication

Total Lines 2905
Duplicated Lines 4.27 %

Coupling/Cohesion

Components 4
Dependencies 6

Importance

Changes 0
Metric Value
dl 124
loc 2905
rs 0.6314
c 0
b 0
f 0
wmc 358
lcom 4
cbo 6

82 Methods

Rating   Name   Duplication   Size   Complexity  
A install() 0 17 2
C update() 0 28 7
B uninstall() 0 29 2
A get() 0 9 3
A getPayment() 0 10 2
A getConnector() 0 4 1
A getService() 0 22 2
A enable() 0 13 2
A disable() 0 10 2
A getKLarnaService() 0 9 2
A getKlarnaAddr() 0 7 2
B createMyEvents() 0 134 2
B onBackendOrderSaveAfter() 0 25 5
A onBackendOrderDeleteAfter() 0 15 3
A onBeforeUpdatePayment() 0 20 3
A onAfterGetCustomerListQueryBuilder() 0 9 1
A onBeforeRegister() 0 7 2
A onPreDispatchAccount() 0 10 4
B onPostDispatchAccount() 3 14 5
A onGetStreetSplitService() 0 9 1
C klarnaLog() 25 25 7
B getKlarnaAddrByRawOrderData() 0 32 3
C fetchStreetAndHouseNumber() 0 40 8
A convertEncoding() 0 13 3
A createMyPayment() 0 23 1
B createMyForm() 0 381 1
C createMyTranslations() 0 54 11
B createMyAttributes() 0 98 4
A registerMyTemplateDir() 0 10 3
A isTemplateResponsive() 0 9 2
A onGetControllerPathFrontend() 0 6 1
A onGetControllerPathBackend() 0 9 1
F onPostDispatch() 17 138 50
F onPostDispatchCheckout() 17 179 40
D onPostDispatchFrontendRegister() 15 43 10
A addJsFiles() 0 8 1
C onPreDispatchCheckout() 0 60 14
A onLoadOrderBackendModule() 16 16 2
A onLoadPaymentBackendModule() 16 16 2
B updateOrderVariables() 0 28 2
A getCountryByShop() 0 13 3
A getCountryIsoById() 0 7 1
B getLocale() 0 21 6
A getCheckoutOptions() 0 16 3
B getCheckoutCart() 0 29 5
B getCheckoutMerchant() 0 42 1
C getCheckoutAddress() 9 37 8
B getCheckoutCustomer() 0 15 5
A getLabel() 0 4 1
A getVersion() 0 10 2
A getInfo() 0 8 1
A onInitResourceKlarnaCheckoutConnector() 0 15 2
A onInitResourceKlarnaService() 0 8 1
A addLessFiles() 0 15 1
A assertMinimumVersion() 0 8 2
A onCheckoutSaveShippingKlarna() 0 14 2
A onCheckoutExpress() 0 8 1
C klarnaMapping() 6 46 12
C getColorConfigOptions() 0 31 13
B getViewConfig() 0 34 1
A getShowLoginConfig() 0 4 2
B getAllCountries() 0 27 2
A getKlarnaDisplayType() 0 7 2
A getOtherPayments() 0 12 3
A getShowCheckoutButton() 0 8 3
B getPositionOrder() 0 18 5
A buildCDNLink() 0 18 2
A getKlarnaCustomerData() 0 21 1
B getTranslationArray() 0 102 1
B updatePayment() 0 29 5
A isKlarnaUser() 0 14 3
B removeKlarnaUsers() 0 42 2
A checkValidKlarnaCountry() 0 8 2
C getExternalPaymentMethods() 0 52 10
A getFee() 0 16 3
A getRedirectUri() 0 7 1
D getImageForKlarna() 0 26 9
A filterPayments() 0 12 3
A isPaymentAllowed() 0 16 3
A buildKlarnaVersion() 0 12 1
A isKpmActive() 0 15 1
A isKlarnaKcoPaymentActive() 0 12 4

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Bootstrap 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 Bootstrap, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Shopware
4
 * Copyright © 2015 shopware AG
5
 *
6
 * According to our dual licensing model, this program can be used either
7
 * under the terms of the GNU Affero General Public License, version 3,
8
 * or under a proprietary license.
9
 *
10
 * The texts of the GNU Affero General Public License with an additional
11
 * permission and of our proprietary license can be found at and
12
 * in the LICENSE file you have received along with this program.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 * GNU Affero General Public License for more details.
18
 *
19
 * "Shopware" is a registered trademark of shopware AG.
20
 * The licensing of the program under the AGPLv3 does not imply a
21
 * trademark license. Therefore any rights, title and interest in
22
 * our trademarks remain entirely with us.
23
 */
24
25
use Doctrine\DBAL\Connection;
26
use Shopware\Components\StreetSplitService;
27
28
# Load dummy interface CSRFWhitelistAware for SW < 5.2
29
require_once __DIR__ . '/Components/CSRFWhitelistAware.php';
30
31
/**
32
 * Shopware Klarna Plugin
33
 */
34
class Shopware_Plugins_Frontend_SwagPaymentKlarna_Bootstrap extends Shopware_Components_Plugin_Bootstrap
35
{
36
    /**
37
     * Get cached countries
38
     * @var array
39
     */
40
    private $countries = array();
41
42
    /**
43
     * The klarna payment object.
44
     * @var \Shopware\Models\Payment\Payment
45
     */
46
    private $klarnaPayment = null;
47
    
48
    /**
49
     * Instance of API-Object
50
     * @var object
51
     */
52
    private $klarnaService = null;
53
54
    /**
55
     * Instance of klarna address object
56
     * @var object
57
     */
58
    private $klarnaAddr = null;
59
60
    /**
61
     * @return array
62
     */
63
    public function install($isUpdate = false)
64
    {
65
        $this->createMyEvents();
66
        if (!$isUpdate) {
67
            $this->createMyPayment();
68
        }
69
        $this->createMyForm();
70
        $this->createMyTranslations();
71
        $this->createMyAttributes();
72
73
        $aReturn = array(
74
            'success' => true,
75
            'invalidateCache' => array('backend')
76
        );
77
        
78
        return $aReturn;
79
    }
80
81
    /**
82
     * @param string $version
83
     * @return bool
84
     */
85
    public function update($version)
86
    {
87
        if ($version == '0.0.1') {
88
            return false;
89
        }
90
91
        if (version_compare($version, '2.0.0', '<')) {
92
            $em = $this->get('models');
93
            $form = $this->Form();
94
            if ($form->getElement('hideCheckoutSteps')) {
95
                $em->remove($form->getElement('hideCheckoutSteps'));
96
            }
97
            if ($form->getElement('expressButton')) {
98
                $em->remove($form->getElement('expressButton'));
99
            }
100
            if ($form->getElement('expressButtonLayer')) {
101
                $em->remove($form->getElement('expressButtonLayer'));
102
            }
103
            if ($form->getElement('noAccountCheckout')) {
104
                $em->remove($form->getElement('noAccountCheckout'));
105
            }
106
            $em->flush();
107
108
            $this->updatePayment();
109
        }
110
111
        return $this->install(true);
112
    }
113
114
    /**
115
     * @return bool
116
     */
117
    public function uninstall()
118
    {
119
        try {
120
            $this->get('models')->removeAttribute(
121
                's_order_attributes',
122
                'swag_klarna',
123
                'status'
124
            );
125
            $this->get('models')->removeAttribute(
126
                's_order_attributes',
127
                'swag_klarna',
128
                'invoice_number'
129
            );
130
            $this->get('models')->removeAttribute(
131
                's_order_details_attributes',
132
                'swag_klarna',
133
                'invoice_number'
134
            );
135
            $this->get('models')->generateAttributeModels(
136
                array(
137
                    's_order_attributes',
138
                    's_order_details_attributes'
139
                )
140
            );
141
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
142
        }
143
144
        return true;
145
    }
146
147
    /**
148
     * @param string $name
149
     * @return mixed
150
     */
151
    public function get($name)
152
    {
153
        if (version_compare(Shopware::VERSION, '4.2.0', '<') && Shopware::VERSION != '___VERSION___') {
154
            $name = ucfirst($name);
155
            return $this->Application()->Bootstrap()->getResource($name);
156
        }
157
158
        return parent::get($name);
159
    }
160
161
    /**
162
     * Fetches and returns klarna payment row instance.
163
     *
164
     * @return \Shopware\Models\Payment\Payment
165
     */
166
    public function getPayment()
167
    {
168
        if ($this->klarnaPayment === null) {
169
            $this->klarnaPayment = $this->Payments()->findOneBy(
170
                array('name' => 'klarna_checkout')
171
            );
172
        }
173
174
        return $this->klarnaPayment;
175
    }
176
177
    /**
178
     * @return \Klarna_Checkout_Connector
179
     */
180
    public function getConnector()
181
    {
182
        return $this->Application()->KlarnaCheckoutConnector();
183
    }
184
185
    /**
186
     * @return \Klarna
187
     */
188
    public function getService()
189
    {
190
        /** @var Klarna $service */
191
        $service = $this->Application()->KlarnaService();
192
        $service->setActivateInfo('flags', KlarnaFlags::RSRV_SEND_BY_EMAIL);
193
        $service->setVersion($this->buildKlarnaVersion($service));
194
        $service->config(
195
            $this->Config()->get('merchantId'),
196
            $this->Config()->get('sharedSecret'),
197
            KlarnaCountry::DE,
198
            KlarnaLanguage::DE,
199
            KlarnaCurrency::EUR,
200
            $this->Config()->get('testDrive') ? Klarna::BETA : Klarna::LIVE,
201
            'pdo',
202
            array(
0 ignored issues
show
Documentation introduced by
array('table' => 's_klar...>Db()->getConnection()) is of type array<string,?,{"table":"string","pdo":"?"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
203
                'table' => 's_klarna_pclasses',
204
                'pdo' => $this->Application()->Db()->getConnection()
205
            )
206
        );
207
208
        return $service;
209
    }
210
211
    /**
212
     * Activate the plugin klarna plugin.
213
     * Sets the active flag in the payment row.
214
     *
215
     * @return bool
216
     */
217
    public function enable()
218
    {
219
        $payment = $this->getPayment();
220
        if ($payment !== null) {
221
            $payment->setActive(true);
222
            $this->get('models')->flush($payment);
223
        }
224
225
        return array(
226
            'success' => true,
227
            'invalidateCache' => array('backend', 'frontend')
228
        );
229
    }
230
231
    /**
232
     * Disable plugin method and sets the active flag in the payment row
233
     *
234
     * @return bool
235
     */
236
    public function disable()
237
    {
238
        $payment = $this->getPayment();
239
        if ($payment !== null) {
240
            $payment->setActive(false);
241
            $this->get('models')->flush($payment);
242
        }
243
244
        return true;
245
    }
246
    
247
    /**
248
     * Returns an instance of klarna object
249
     * 
250
     * @param void
251
     * @return \Klarna
252
     */
253
    public function getKLarnaService() {
254
        if ($this->klarnaService === null) {
255
            require_once __DIR__ . '/Components/Klarna/Klarna.php';
256
            require_once __DIR__ . '/Components/Klarna/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
257
            $this->klarnaService = new Klarna();
258
        }
259
260
        return $this->klarnaService;
261
    }
262
    
263
    /**
264
     * Returns an instance of klarna address object
265
     * 
266
     * @param void
267
     * @return object
268
     */
269
    public function getKlarnaAddr() {
270
        if ($this->klarnaAddr === null) {
271
            $this->klarnaAddr = new KlarnaAddr();
272
        }
273
        
274
        return $this->klarnaAddr;
275
    }
276
277
    /**
278
     * Creates and subscribe the events and hooks.
279
     */
280
    protected function createMyEvents()
281
    {
282
        // BACKEND
283
        $this->subscribeEvent(
284
            'Enlight_Controller_Action_PostDispatch_Backend_Order',
285
            'onLoadOrderBackendModule'
286
        );
287
        $this->subscribeEvent(
288
            'Enlight_Controller_Action_PostDispatch_Backend_Payment',
289
            'onLoadPaymentBackendModule'
290
        );
291
292
        $this->subscribeEvent(
293
            'Enlight_Controller_Dispatcher_ControllerPath_Backend_PaymentKlarna',
294
            'onGetControllerPathBackend'
295
        );
296
297
        // FRONTEND
298
        $this->subscribeEvent(
299
            'Enlight_Controller_Dispatcher_ControllerPath_Frontend_PaymentKlarna',
300
            'onGetControllerPathFrontend'
301
        );
302
303
        $this->subscribeEvent(
304
            'Enlight_Controller_Action_PostDispatch_Frontend_Checkout',
305
            'onPostDispatchCheckout'
306
        );
307
308
        $this->subscribeEvent(
309
            'Enlight_Controller_Action_PreDispatch_Frontend_Checkout',
310
            'onPreDispatchCheckout'
311
        );
312
313
        $this->subscribeEvent(
314
            'Enlight_Controller_Action_Frontend_Checkout_Express',
315
            'onCheckoutExpress'
316
        );
317
318
        $this->subscribeEvent(
319
            'Enlight_Controller_Action_Frontend_Checkout_saveShippingKlarna',
320
            'onCheckoutSaveShippingKlarna'
321
        );
322
323
        $this->subscribeEvent(
324
            'Enlight_Controller_Action_PostDispatch',
325
            'onPostDispatch',
326
            110
327
        );
328
329
        // CONNECTOR
330
        $this->subscribeEvent(
331
            'Enlight_Bootstrap_InitResource_KlarnaCheckoutConnector',
332
            'onInitResourceKlarnaCheckoutConnector'
333
        );
334
335
        // SERVICES
336
        $this->subscribeEvent(
337
            'Enlight_Bootstrap_InitResource_KlarnaService',
338
            'onInitResourceKlarnaService'
339
        );
340
341
        $this->subscribeEvent(
342
            'Enlight_Bootstrap_InitResource_StreetSplitService',
343
            'onGetStreetSplitService'
344
        );
345
346
        $this->subscribeEvent(
347
            'Enlight_Controller_Action_PostDispatch_Frontend_Register',
348
            'onPostDispatchFrontendRegister'
349
        );
350
351
        $this->subscribeEvent(
352
            'Enlight_Controller_Action_PreDispatch_Frontend_Account',
353
            'onPreDispatchAccount'
354
        );
355
356
        $this->subscribeEvent(
357
            'Enlight_Controller_Action_PostDispatch_Frontend_Account',
358
            'onPostDispatchAccount'
359
        );
360
        $this->subscribeEvent(
361
            'Enlight_Controller_Action_PostDispatch_Frontend_Checkout',
362
            'onPostDispatchAccount'
363
        );
364
365
        $this->subscribeEvent(
366
            'Shopware\Models\Customer\Repository::getListQueryBuilder::after',
367
            'onAfterGetCustomerListQueryBuilder'
368
        );
369
370
        $this->subscribeEvent(
371
            'Theme_Compiler_Collect_Plugin_Javascript',
372
            'addJsFiles'
373
        );
374
375
        // LESS
376
        // Subscribe the needed event for less merge and compression
377
        $this->subscribeEvent(
378
            'Theme_Compiler_Collect_Plugin_Less',
379
            'addLessFiles'
380
        );
381
382
        #########
383
        # HOOKS   #
384
        #########
385
386
        if (version_compare(Shopware::VERSION, '5.2.0', '>=')) {
387
            $this->subscribeEvent(
388
                'sAdmin::saveRegisterAction::before',
389
                'onBeforeRegister'
390
            );
391
        }
392
        else {
393
            $this->subscribeEvent(
394
                'sAdmin::sSaveRegister::before',
395
                'onBeforeRegister'
396
            );
397
        }
398
399
        $this->subscribeEvent(
400
            'Shopware_Controllers_Backend_Payment::updatePaymentsAction::before',
401
            'onBeforeUpdatePayment'
402
        );
403
        
404
        $this->subscribeEvent(
405
            'Shopware_Controllers_Backend_Order::saveAction::after',
406
            'onBackendOrderSaveAfter'
407
        );    
408
        $this->subscribeEvent(
409
            'Shopware_Controllers_Backend_Order::deleteAction::after',
410
            'onBackendOrderDeleteAfter'
411
        );          
412
        
413
    }
414
415
    /**
416
     * Method will be triggered on clicking save on order details
417
     * 
418
     * @param Enlight_Hook_HookArgs $args
419
     * @return void
420
     */
421
    public function onBackendOrderSaveAfter(Enlight_Hook_HookArgs $args) {
422
        $orderDataRaw = $args->getSubject()->Request()->getPost();
423
        $paymentName = $orderDataRaw['payment'][0]['name'];
424
        
425
        if ($paymentName == 'klarna_checkout' || $paymentName == 'klarna_account' || $paymentName == 'klarna_invoice') {
426
            // require_once __DIR__ . '/Models/lightConnector.php';
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
427
            
428
            $klarnaService = $this->getService();
429
            
430
            $klarnaAddrBilling = $this->getKlarnaAddrByRawOrderData($orderDataRaw,'billing');
431
            $klarnaAddrShipping = $this->getKlarnaAddrByRawOrderData($orderDataRaw,'shipping');
432
            
433
            $orderId = $orderDataRaw['id'];
0 ignored issues
show
Unused Code introduced by
$orderId is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
434
            $transactionId = $orderDataRaw['transactionId'];
435
            $klarnaOrderId = $orderDataRaw['temporaryId'];
0 ignored issues
show
Unused Code introduced by
$klarnaOrderId is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
436
            
437
            $klarnaService->setAddress(KlarnaFlags::IS_BILLING, $klarnaAddrBilling);
0 ignored issues
show
Security Bug introduced by
It seems like $klarnaAddrBilling defined by $this->getKlarnaAddrByRa...rderDataRaw, 'billing') on line 430 can also be of type false; however, Klarna::setAddress() does only seem to accept object<KlarnaAddr>, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
438
            $klarnaService->setAddress(KlarnaFlags::IS_SHIPPING, $klarnaAddrShipping);
0 ignored issues
show
Security Bug introduced by
It seems like $klarnaAddrShipping defined by $this->getKlarnaAddrByRa...derDataRaw, 'shipping') on line 431 can also be of type false; however, Klarna::setAddress() does only seem to accept object<KlarnaAddr>, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
439
            try {
440
                $klarnaService->update($transactionId);
441
            } catch (Exception $e) {
442
                throw new Exception($e->getMessage());
443
            }
444
        }
445
    }
446
    
447
    /**
448
     * Method will be triggered on clicking delete on order overview
449
     * 
450
     * @param Enlight_Hook_HookArgs $args
451
     * @return void
452
     */
453
    public function onBackendOrderDeleteAfter(Enlight_Hook_HookArgs $args) {
454
        $orderDataRaw = $args->getSubject()->Request()->getPost();
455
        $paymentName = $orderDataRaw['payment'][0]['name'];
456
        
457
        if ($paymentName == 'klarna_checkout') {
458
            
459
            $klarnaService = $this->getService();
460
            $transactionId = $orderDataRaw['transactionId'];
461
            try {
462
                $klarnaService->cancelReservation($transactionId);
463
            } catch (Exception $e) {
464
                throw new Exception($e->getMessage());
465
            }
466
        }
467
    }    
468
    
469
    
470
    /**
471
     * Hook to change the absolute media-path to a normalized virtual path.
472
     * @param Enlight_Hook_HookArgs $args
473
     */
474
    public function onBeforeUpdatePayment(Enlight_Hook_HookArgs $args)
475
    {
476
        if (!$this->assertMinimumVersion('5.1')) {
477
            return;
478
        }
479
480
        /** @var Zend_Controller_Request_Http $request */
481
        $request = $args->getSubject()->Request();
482
        $attributes = $request->getParam('attribute');
483
        $attribute = reset($attributes);
484
485
        if (empty($attribute['swagKlarnaKlarnaMedia'])) {
486
            return;
487
        }
488
489
        $mediaService = $this->get('shopware_media.media_service');
490
        $attribute['swagKlarnaKlarnaMedia'] = $mediaService->normalize($attribute['swagKlarnaKlarnaMedia']);
491
        $attributes[0] = $attribute;
492
        $request->setParam('attribute', $attributes);
493
    }
494
495
    /**
496
     * Needed to implement an additional "where"-condition to filter temporary klarna-customers, so they won't be shown
497
     * in the backend anymore.
498
     *
499
     * @param Enlight_Hook_HookArgs $args
500
     */
501
    public function onAfterGetCustomerListQueryBuilder(Enlight_Hook_HookArgs $args)
502
    {
503
        /** @var \Doctrine\DBAL\Query\QueryBuilder $builder */
504
        $builder = $args->getReturn();
505
506
        $builder->andWhere('billing.lastName != :lastName')->setParameter('lastName', 'Klarna Checkout');
507
508
        $args->setReturn($builder);
509
    }
510
511
    /**
512
     * Sets the default-payment to klarna checkout.
513
     */
514
    public function onBeforeRegister()
515
    {
516
        $register = $this->Application()->Session()->offsetGet('sRegister');
517
        if ($register["payment"]["object"]["id"] === $this->getPayment()->getId()) {
518
            unset($register["payment"]["object"]["id"]);
519
        }
520
    }
521
522
    /**
523
     * Only used in emotion-template.
524
     * Logs out the user when entering the
525
     * @param Enlight_Event_EventArgs $args
526
     */
527
    public function onPreDispatchAccount(Enlight_Event_EventArgs $args)
528
    {
529
        /** @var Shopware_Controllers_Frontend_Account $subject */
530
        $subject = $args->getSubject();
531
        $request = $subject->Request();
532
533
        if ($this->isKlarnaUser() && !$this->isTemplateResponsive() && $request->getActionName() != 'savePayment') {
534
            $subject->logoutAction();
535
        }
536
    }
537
538
    /**
539
     * Needed to delete temporary accounts, when the user changes the payment.
540
     *
541
     * @param Enlight_Controller_ActionEventArgs $args
542
     */
543
    public function onPostDispatchAccount(Enlight_Controller_ActionEventArgs $args)
544
    {
545
        $request = $args->getRequest();
546
        $response = $args->getResponse();
547 View Code Duplication
        if (!$this->isKlarnaUser() || !$request->isDispatched() || $response->isException() || $request->getActionName() == 'confirm') {
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...
548
            return;
549
        }
550
        $session = Shopware()->Session();
551
        //Logout user
552
        $session->offsetUnset('sUserId');
553
        $session->offsetSet('sRegisterFinished', false);
554
        //Remove all temporary klarna-users older than 24 hours
555
        $this->removeKlarnaUsers();
556
    }
557
558
    public function onGetStreetSplitService()
559
    {
560
        $this->Application()->Loader()->registerNamespace(
561
            'Shopware\Components',
562
            __DIR__ . '/Components/'
563
        );
564
565
        return new StreetSplitService();
566
    }
567
    
568
    /**
569
     * Logs a message
570
     * 
571
     * @param string $message
572
     * @param int $logLevelMessage
573
     * @param mixed $mPrintableElement
574
     * @return void
575
     */
576 View Code Duplication
    public function klarnaLog($message, $logLevelMessage=1, $mPrintableElement=null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
577
        $configname = 'klarnaLogLevel';
578
        $elementId = Shopware()->Db()->fetchOne('SELECT id FROM s_core_config_elements WHERE name = ?', [$configname]);
579
        $logLevelConfigSetting = Shopware()->Db()->fetchOne('SELECT value FROM s_core_config_values WHERE element_id = ?', [$elementId]);
580
        $logLevelConfigSetting = unserialize($logLevelConfigSetting);
581
        $logLevelSetting = (is_numeric($logLevelConfigSetting) && $logLevelConfigSetting >=0 && $logLevelConfigSetting <=4) ? (int)$logLevelConfigSetting : 1;
582
        
583
        if ($logLevelMessage <= $logLevelSetting) {
584
            $prefix = "[".date('Y-m-d H:i:s')."] ";
585
            $debugBacktrace = '';
586
            if ($logLevelSetting >= 4) {
587
                $debugBacktrace = print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS),true);
588
            }
589
            $sPrintableElementMessage = '';
590
            if ($mPrintableElement !== null) {
591
                $sPrintableElementMessage = print_r($mPrintableElement,true);
592
            }
593
            $fullMessage = $prefix.$message."\n".$sPrintableElementMessage.$debugBacktrace;
594
            $shopPath = Shopware()->DocPath();
595
            $logfilePath = $shopPath.'/var/log/klarnaTrace.log';
596
            $fileHandler = fopen($logfilePath,'a');
597
            fwrite($fileHandler, $fullMessage);
598
            fclose($fileHandler);
599
        }
600
    }
601
    
602
    /**
603
     * Method returns matching address parts by address type
604
     * 
605
     * @param array $orderDataRaw
606
     * @param string $type
607
     */
608
    protected function getKlarnaAddrByRawOrderData($orderDataRaw, $type) {
609
        $klarnaAddr = false;
610
        $baseData = (isset($orderDataRaw[$type][0])) ? $orderDataRaw[$type][0] : false;
611
        $baseData = $this->convertEncoding($baseData);
612
        
613
        if ($baseData) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $baseData 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...
614
            $addressParts = $this->fetchStreetAndHouseNumber($baseData);
615
616
            $manager = $this->get('models');
617
            $repository = 'Shopware\Models\Country\Country';
618
            $repository = $manager->getRepository($repository);
619
            $country = $repository->findOneBy(array('id' => $baseData['countryId']));
620
            $countryiso = $country->getIso();
621
622
            $klarnaAddr =  new KlarnaAddr();
623
            $klarnaAddr->setEmail($orderDataRaw['customerEmail']);
624
            $klarnaAddr->setFirstName($baseData['firstName']);
625
            $klarnaAddr->setLastName($baseData['lastName']);
626
            $klarnaAddr->setTelno($baseData['phone']);
627
            $klarnaAddr->setStreet($addressParts['street']);
628
            $klarnaAddr->setHouseNumber($addressParts['streetnr']);
629
            $klarnaAddr->setHouseExt($addressParts['streetnr_extension']);
630
            $klarnaAddr->setCompanyName($baseData['company']);
631
            $klarnaAddr->setCareof($baseData['department']);
632
            $klarnaAddr->setZipCode($baseData['zipCode']);
633
            $klarnaAddr->setCity($baseData['city']);
634
            $klarnaAddr->setCountry($countryiso);
635
        }
636
637
        $this->klarnaLog('Update order address from backend with following address data:',3,$klarnaAddr);
638
        return $klarnaAddr;
639
    }
640
641
642
    /**
643
     * Method splits street, streetnr and streetnr extension from basestring
644
     *
645
     * @param array $baseData
646
     * @return array
647
     */
648
    protected function fetchStreetAndHouseNumber($baseData) {
649
650
        $addressParts = explode(' ', $baseData['street']);
651
        $index = 0;
652
        $street = $streetnr = '';
653
        $houseNumberFound = false;
654
655
        foreach ($addressParts as $addressPart) {
656
            if (!$houseNumberFound) {
657
                // check if current addresspart is numeric
658
                $houseNumberFound = is_numeric($addressPart);
659
            }
660
661
            $index++;
662
            if ($index == count($addressParts) || $houseNumberFound) {
663
                // at least last element should be streetnr
664
                if (!empty($streetnr)) $streetnr .= ' ';
665
                $streetnr .= (string)$addressPart;
666
            }
667
            else  {
668
                $street .= (string)' '.$addressPart;
669
            }
670
        }
671
672
        $streetnr_extension = '';
673
        if (!empty($baseData['additionalAddressLine1'])) {
674
            $streetnr_extension .= $baseData['additionalAddressLine1'];
675
        }
676
        if (!empty($baseData['additionalAddressLine2'])) {
677
            $streetnr_extension .= "\n".$baseData['additionalAddressLine2'];
678
        }
679
680
        $return = array(
681
            'street' => $street,
682
            'streetnr' => $streetnr,
683
            'streetnr_extension' => $streetnr_extension,
684
        );
685
686
        return $return;
687
    }
688
    
689
690
    /**
691
     * Converts encoding in all string fields of an array
692
     * 
693
     * @param array $data
694
     * @return array
695
     */
696
    protected function convertEncoding($data) {
697
        $out = array();
698
        foreach ($data as $key=>$value) {
699
            if (is_string($value)) {
700
                $value = mb_convert_encoding($value, 'ISO-8859-1', 'UTF-8');
701
                // $value = utf8_decode($value);
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
702
            }
703
            
704
            $out[$key] = $value;
705
        }
706
        
707
        return $out;
708
    }
709
710
    /**
711
     * Creates and save the payment row.
712
     */
713
    protected function createMyPayment()
714
    {
715
        /** @var \Shopware\Components\Model\ModelManager $manager */
716
        $manager = $this->get('models');
717
        $repository = 'Shopware\Models\Country\Country';
718
        $repository = $manager->getRepository($repository);
719
        $countries = array(
720
            $repository->findOneBy(array('iso' => 'SE')),
721
            $repository->findOneBy(array('iso' => 'DE')),
722
            $repository->findOneBy(array('iso' => 'NO')),
723
            $repository->findOneBy(array('iso' => 'FI')),
724
            $repository->findOneBy(array('iso' => 'AT'))
725
        );
726
        $this->createPayment(
727
            array(
728
                'name' => 'klarna_checkout',
729
                'description' => $this->getLabel(),
730
                'action' => 'payment_klarna',
731
                'additionalDescription' => '',
732
                'countries' => $countries
733
            )
734
        );
735
    }
736
737
    /**
738
     * Creates and stores the payment config form.
739
     */
740
    protected function createMyForm()
741
    {
742
        $form = $this->Form();
743
744
        // API settings
745
        $form->setElement(
746
            'boolean',
747
            'testDrive',
748
            array(
749
                'label' => 'Testmodus aktvieren',
750
                'value' => false,
751
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
752
                'position' => 0
753
            )
754
        );
755
756
        $form->setElement(
757
            'text',
758
            'merchantId',
759
            array(
760
                'label' => 'API-HändlerID (EID)',
761
                'required' => true,
762
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
763
                'position' => 1
764
            )
765
        );
766
767
        $form->setElement(
768
            'text',
769
            'sharedSecret',
770
            array(
771
                'label' => 'API-Secret (sharedsecret)',
772
                'required' => true,
773
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
774
                'position' => 2
775
            )
776
        );
777
778
        $form->setElement(
779
            'number',
780
            'termSiteId',
781
            array(
782
                'label' => 'Shopseite mit den Geschäftsbedingungen',
783
                'value' => 4,
784
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
785
                'position' => 3
786
            )
787
        );
788
789
        $form->setElement(
790
            'boolean',
791
            'allowSeparateShippingAddress',
792
            array(
793
                'label' => 'Abweichende Lieferadresse erlauben',
794
                'value' => true,
795
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
796
                'position' => 4
797
            )
798
        );
799
800
        $form->setElement(
801
            'boolean',
802
            'supportPackstation',
803
            array(
804
                'label' => 'DHL Packstation unterstützen',
805
                'value' => false,
806
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
807
                'position' => 5,
808
                'helpText' => 'Die abweichende Lieferadresse muss erlaubt sein'
809
            )
810
        );
811
812
        $form->setElement(
813
            'text',
814
            'postnumberField',
815
            array(
816
                'label' => 'Alternatives Feld für die DHL-Postnummer',
817
                'value' => 'attribute1',
818
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
819
                'position' => 6
820
            )
821
        );
822
823
        $form->setElement(
824
            'boolean',
825
            'mandatoryPhone',
826
            array(
827
                'label' => 'Telefonummer als Pflichtfeld',
828
                'value' => false,
829
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
830
                'position' => 7
831
            )
832
        );
833
834
        $form->setElement(
835
            'boolean',
836
            'mandatoryBirthday',
837
            array(
838
                'label' => 'Geburtsdatum als Pflichtfeld',
839
                'value' => false,
840
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
841
                'position' => 8
842
            )
843
        );
844
845
        $form->setElement(
846
            'boolean',
847
            'disableAutofocus',
848
            array(
849
                'label' => 'Autofokus deaktivieren',
850
                'value' => false,
851
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
852
                'position' => 9
853
            )
854
        );
855
856
        $form->setElement(
857
            'boolean',
858
            'showKlarnaButton',
859
            array(
860
                'label' => 'Klarna Checkout-Button anzeigen',
861
                'value' => true,
862
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
863
                'position' => 10
864
            )
865
        );
866
867
        $form->setElement(
868
            'boolean',
869
            'preFillCheckout',
870
            array(
871
                'label' => 'Klarna Checkout für registrierte Kunden vorausfüllen',
872
                'value' => true,
873
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
874
                'position' => 11
875
            )
876
        );
877
878
        $form->setElement(
879
            'color',
880
            'checkoutButtonColor',
881
            array(
882
                'label' => 'Checkout Button Farbe',
883
                'value' => null,
884
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
885
                'position' => 12
886
            )
887
        );
888
889
        $form->setElement(
890
            'color',
891
            'checkoutButtonTextColor',
892
            array(
893
                'label' => 'Checkout Buttontext Farbe',
894
                'value' => null,
895
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
896
                'position' => 13
897
            )
898
        );
899
900
        $form->setElement(
901
            'color',
902
            'checkoutCheckboxColor',
903
            array(
904
                'label' => 'Checkout Checkbox Farbe',
905
                'value' => null,
906
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
907
                'position' => 14
908
            )
909
        );
910
911
        $form->setElement(
912
            'color',
913
            'checkoutCheckboxCheckmarkColor',
914
            array(
915
                'label' => 'Checkout Checkbox Häckchen Farbe',
916
                'value' => null,
917
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
918
                'position' => 15
919
            )
920
        );
921
922
        $form->setElement(
923
            'color',
924
            'checkoutHeaderColor',
925
            array(
926
                'label' => 'Checkout Header Farbe',
927
                'value' => null,
928
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
929
                'position' => 16
930
            )
931
        );
932
933
        $form->setElement(
934
            'color',
935
            'checkoutLinkColor',
936
            array(
937
                'label' => 'Checkout Link Farbe',
938
                'value' => null,
939
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
940
                'position' => 17
941
            )
942
        );
943
944
        $form->setElement(
945
            'boolean',
946
            'KlarnaExternalPayments',
947
            array(
948
                'label' => 'Externe Zahlungsarten im Klarna Checkout darstellen',
949
                'value' => null,
950
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
951
                'helpText' => 'Ihr Klarna-Konto muss für diese Funktion freigeschaltet werden',
952
                'position' => 18
953
            )
954
        );
955
956
        $form->setElement(
957
            'select',
958
            'displayType',
959
            array(
960
                'label' => 'Klarna Checkout Darstellungs-Art',
961
                'value' => 1,
962
                'store' => array(
963
                    array(1, 'Tab-Darstellung'),
964
                    array(2, 'Nur Klarna Checkout-Darstellung'),
965
                    array(3, 'Einseiten-Darstellung')
966
                ),
967
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
968
                'position' => 19
969
            )
970
        );
971
972
        $form->setElement(
973
            'boolean',
974
            'showB2bSelect',
975
            array(
976
                'label' => 'B2B-Auswahl anzeigen',
977
                'value' => true,
978
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
979
                'helpText' => 'In dem Klarna Checkout wird eine Auswahl "Privatkunde / Firma" angezeigt',
980
                'position' => 20
981
            )
982
        );
983
984
        $form->setElement(
985
            'boolean',
986
            'showLoginPanel',
987
            array(
988
                'label' => 'Login-Formular anzeigen',
989
                'value' => true,
990
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
991
                'helpText' => 'In dem Klarna Checkout wird ein Login-Formular angezeigt',
992
                'position' => 21
993
            )
994
        );
995
996
        $form->setElement(
997
            'boolean',
998
            'showMiniBasket',
999
            array(
1000
                'label' => 'Warenkorb anzeigen',
1001
                'value' => true,
1002
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
1003
                'helpText' => 'In dem Klarna Checkout wird eine kleine Übersicht des Warenkorbs angezeigt',
1004
                'position' => 22
1005
            )
1006
        );
1007
1008
        $form->setElement(
1009
            'boolean',
1010
            'showDispatch',
1011
            array(
1012
                'label' => 'Lieferland & Versandarten anzeigen',
1013
                'value' => true,
1014
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
1015
                'helpText' => 'In dem Klarna Checkout wird eine Lieferland- sowie Versandarten-Auswahl angezeigt',
1016
                'position' => 23
1017
            )
1018
        );
1019
1020
        $form->setElement(
1021
            'select',
1022
            'positionOrder',
1023
            array(
1024
                'label' => 'Reihenfolge der Elemente',
1025
                'value' => 1,
1026
                'store' => array(
1027
                    array(1, 'Login-Formular, Mini-Warenkorb, Versandauswahl, Zahlungsauswahl'),
1028
                    array(2, 'Login-Formular, Mini-Warenkorb, Zahlungsauswahl, Versandauswahl'),
1029
                    array(3, 'Versandauswahl, Zahlungsauswahl, Login-Formular, Mini-Warenkorb'),
1030
                    array(4, 'Zahlungsauswahl, Versandauswahl, Login-Formular, Mini-Warenkorb')
1031
                ),
1032
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
1033
                'helpText' => 'Die \'Zahlungsauswahl\' wird nur in der \'Einseitig\'-Darstellung angezeigt.',
1034
                'position' => 24
1035
            )
1036
        );
1037
1038
        $form->setElement(
1039
            'boolean',
1040
            'partPaymentWidget',
1041
            array(
1042
                'label' => 'Teilzahlungs-Widget auf der Detailseite anzeigen',
1043
                'value' => true,
1044
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
1045
                'position' => 25
1046
            )
1047
        );
1048
1049
        $form->setElement(
1050
            'boolean',
1051
            'convertShippingFee',
1052
            array(
1053
                'label' => 'Versandkosten in eine Bestellposition umwandeln',
1054
                'value' => true,
1055
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
1056
                'position' => 26
1057
            )
1058
        );
1059
1060
        $form->setElement(
1061
            'select',
1062
            'statusId',
1063
            array(
1064
                'label' => 'Zahlstatus nach der Bestellung',
1065
                'value' => 18,
1066
                'store' => 'base.PaymentStatus',
1067
                'displayField' => 'description',
1068
                'valueField' => 'id',
1069
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
1070
                'position' => 27
1071
            )
1072
        );
1073
1074
        $form->setElement(
1075
            'select',
1076
            'activateStatusId',
1077
            array(
1078
                'label' => 'Zahlungsstatus nach der Aktivierung',
1079
                'value' => 12,
1080
                'store' => 'base.PaymentStatus',
1081
                'displayField' => 'description',
1082
                'valueField' => 'id',
1083
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
1084
                'position' => 28
1085
            )
1086
        );
1087
1088
        $form->setElement(
1089
            'select',
1090
            'cancelStatusId',
1091
            array(
1092
                'label' => 'Zahlungsstatus nach der Stornierung',
1093
                'value' => 17,
1094
                'store' => 'base.PaymentStatus',
1095
                'displayField' => 'description',
1096
                'valueField' => 'id',
1097
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
1098
                'position' => 29
1099
            )
1100
        );
1101
        
1102
        $form->setElement(
1103
            'select',
1104
            'klarnaLogLevel',
1105
            array(
1106
                'label' => 'Detaillevel der Logeinträge zur Fehlerverfolgung',
1107
                'value' => 0,
1108
                'store' => array(
1109
                    array(0, 'Nichts protokollieren'),
1110
                    array(1, 'Nur Fehler protokollieren'),
1111
                    array(2, 'Fehler und Warnungen protokollieren'),
1112
                    array(3, 'Alle Meldungen protokollieren'),
1113
                    array(4, 'Alle Meldungen und zusätzlich Entwicklerinformationen protokollieren (Große Logdateien!)'),
1114
                ),
1115
                'scope' => \Shopware\Models\Config\Element::SCOPE_SHOP,
1116
                'helpText' => 'Diese Einstellmöglichkeit dient vor allem der Nachverfolgung von Fehlern im Ablauf. Die Logdatei finden Sie unter var/log/klarnaTrace.log ihrer Shopware-Installation.',
1117
                'position' => 30
1118
            )
1119
        );
1120
    }
1121
1122
    /**
1123
     *
1124
     */
1125
    public function createMyTranslations()
1126
    {
1127
        $form = $this->Form();
1128
        $translations = $this->getTranslationArray();
1129
1130
        // In 4.2.2 we introduced a helper function for this, so we can skip the custom logic
1131
        if ($this->assertMinimumVersion('4.2.2')) {
1132
            $this->addFormTranslations($translations);
1133
            return true;
1134
        }
1135
1136
        $shopRepository = Shopware()->Models()->getRepository('\Shopware\Models\Shop\Locale');
1137
        foreach ($translations as $locale => $snippets) {
1138
            /** @var \Shopware\Models\Shop\Locale|null $localeModel */
1139
            $localeModel = $shopRepository->findOneBy(array('locale' => $locale));
1140
            if ($localeModel === null) {
1141
                continue;
1142
            }
1143
            foreach ($snippets as $element => $snippet) {
1144
                $translationModel = null;
1145
                //get the form element by name
1146
                $elementModel = $form->getElement($element);
1147
1148
                //not found? continue with next snippet
1149
                if ($elementModel === null) {
1150
                    continue;
1151
                }
1152
1153
                // Try to load existing translation
1154
                foreach ($elementModel->getTranslations() as $translation) {
1155
                    if ($translation->getLocale()->getLocale() == $locale) {
1156
                        $translationModel = $translation;
1157
                        break;
1158
                    }
1159
                }
1160
1161
                // If none found create a new one
1162
                if (!$translationModel) {
1163
                    $translationModel = new \Shopware\Models\Config\ElementTranslation();
1164
                    $translationModel->setLocale($localeModel);
1165
                    //add the translation to the form element
1166
                    $elementModel->addTranslation($translationModel);
1167
                }
1168
1169
                if ($snippet['label']) {
1170
                    $translationModel->setLabel($snippet['label']);
1171
                }
1172
1173
                if ($snippet['description']) {
1174
                    $translationModel->setDescription($snippet['description']);
1175
                }
1176
            }
1177
        }
1178
    }
1179
1180
    /**
1181
     *
1182
     */
1183
    public function createMyAttributes()
1184
    {
1185
        try {
1186
            $this->get('models')->addAttribute(
1187
                's_order_details_attributes',
1188
                'swag_klarna',
1189
                'invoice_number',
1190
                'VARCHAR(255)'
1191
            );
1192
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
1193
        }
1194
1195
        $this->get('models')->generateAttributeModels(
1196
            array(
1197
                's_order_details_attributes'
1198
            )
1199
        );
1200
1201
        try {
1202
            $this->get('models')->addAttribute(
1203
                's_order_attributes',
1204
                'swag_klarna',
1205
                'status',
1206
                'VARCHAR(255)'
1207
            );
1208
            $this->get('models')->addAttribute(
1209
                's_order_attributes',
1210
                'swag_klarna',
1211
                'invoice_number',
1212
                'VARCHAR(255)'
1213
            );
1214
1215
            $this->get('models')->addAttribute(
1216
                's_core_paymentmeans_attributes',
1217
                'swag_klarna',
1218
                'show_in_klarna_iframe',
1219
                'int(11)'
1220
            );
1221
            $this->get('models')->addAttribute(
1222
                's_core_paymentmeans_attributes',
1223
                'swag_klarna',
1224
                'allow_in_payment_container',
1225
                'int(11)'
1226
            );
1227
            $this->get('models')->addAttribute(
1228
                's_core_paymentmeans_attributes',
1229
                'swag_klarna',
1230
                'klarna_media',
1231
                'VARCHAR(255)'
1232
            );
1233
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
1234
        }
1235
1236
        $this->get('models')->generateAttributeModels(
1237
            array(
1238
                's_order_attributes',
1239
                's_core_paymentmeans_attributes'
1240
            )
1241
        );
1242
        
1243
        if ($this->assertMinimumVersion('5.2')) {
1244
            $this->get('shopware_attribute.crud_service')->update(
1245
                's_core_paymentmeans_attributes',
1246
                'swag_klarna_show_in_klarna_iframe',
1247
                'boolean',
1248
                [
1249
                    'label' => 'In Klarna Checkout einbinden',
1250
                    'helpText' => 'Bindet die Zahlungsart direkt in das Klarna iFrame ein',
1251
                    'displayInBackend' => true,
1252
                    'pluginId' => $this->getId()
1253
                ]
1254
            );
1255
            $this->get('shopware_attribute.crud_service')->update(
1256
                's_core_paymentmeans_attributes',
1257
                'swag_klarna_allow_in_payment_container',
1258
                'boolean',
1259
                [
1260
                    'label' => 'Nicht neben dem Klarna Checkout anzeigen',
1261
                    'helpText' => 'Versteckt die Zahlungsart in dem "Andere Zahlungsarten-Container" im Klarna Checkout',
1262
                    'displayInBackend' => true,
1263
                    'pluginId' => $this->getId()
1264
                ]
1265
            );    
1266
            $this->get('shopware_attribute.crud_service')->update(
1267
                's_core_paymentmeans_attributes',
1268
                'swag_klarna_klarna_media',
1269
                'string',
1270
                [
1271
                    'label' => 'Bild Name für Klarna Checkout',
1272
                    'helpText' => 'Zeigt die Zahlungsart zusätzlich mit einem Bild im iFrame an. Funktioniert nur, wenn SSL konfiguriert ist. Optimale Größe: 276x48px.'
1273
                    . 'Das Bild muss im Order /media/image gespeichert werden',
1274
                    'displayInBackend' => true,
1275
                    'pluginId' => $this->getId()
1276
                ]
1277
            );             
1278
            
1279
        }        
1280
    }
1281
1282
    protected function registerMyTemplateDir($isBackend = false)
1283
    {
1284
        if ($isBackend) {
1285
            $this->get('template')->addTemplateDir(__DIR__ . '/Views/', 'klarna');
1286
        } elseif ($this->isTemplateResponsive()) {
1287
            $this->get('template')->addTemplateDir(__DIR__ . '/Views/responsive', 'klarna');
1288
        } else {
1289
            $this->get('template')->addTemplateDir(__DIR__ . '/Views/_emotion', 'klarna');
1290
        }
1291
    }
1292
1293
    /**
1294
     * Checks if the the current Template is responsive
1295
     *
1296
     * @return bool
1297
     */
1298
    private function isTemplateResponsive()
1299
    {
1300
        $template = $this->Application()->Shop()->getTemplate()->getVersion();
1301
        if ($template < 3) {
1302
            return false;
1303
        }
1304
1305
        return true;
1306
    }
1307
1308
    /**
1309
     * Returns the path to a frontend controller for an event.
1310
     *
1311
     * @return string
1312
     */
1313
    public function onGetControllerPathFrontend()
1314
    {
1315
        $this->registerMyTemplateDir();
1316
1317
        return __DIR__ . '/Controllers/Frontend/PaymentKlarna.php';
1318
    }
1319
1320
    /**
1321
     * Returns the path to a backend controller for an event.
1322
     *
1323
     * @return string
1324
     */
1325
    public function onGetControllerPathBackend()
1326
    {
1327
        $this->registerMyTemplateDir(true);
1328
        $this->Application()->Snippets()->addConfigDir(
1329
            __DIR__ . '/Snippets/'
1330
        );
1331
1332
        return __DIR__ . '/Controllers/Backend/PaymentKlarna.php';
1333
    }
1334
1335
    /**
1336
     * @param Enlight_Event_EventArgs $args
1337
     */
1338
    public function onPostDispatch(Enlight_Event_EventArgs $args)
1339
    {
1340
        /** @var $action Enlight_Controller_Action */
1341
        $action = $args->getSubject();
1342
        $request = $action->Request();
1343
        $response = $action->Response();
1344
        $view = $action->View();
1345
        
1346
        if ($request->getControllerName() == 'account' && $request->getActionName() == 'login'
1347
          && $request->get('klarnaPreFill') && $response->isRedirect()) {
1348
            $session = $this->get('session');
1349
            $session['klarnaPreFill'] = true;
1350
        }
1351
1352
        if (!$request->isDispatched()
1353
            || $response->isException()
1354
            || $request->getModuleName() != 'frontend'
1355
            || !$view->hasTemplate()
1356
        ) {
1357
            return;
1358
        }
1359
1360
        $postedCountry = $request->get('sCountry');
1361
        $controllerName = $request->getControllerName();
1362
        $actionName = $request->getActionName();
1363
        $fromScope = $request->get('fromScope');
1364
        $isFromKCO = (bool)($fromScope == 'klarna_checkout');
1365
        
1366
        $session = $this->get('session');
1367
        
1368
        if ($controllerName == 'payment_klarna' && $postedCountry !== null) {
1369
            $shopCountryId = $this->getCountryByShop(Shopware()->Shop());
1370
            $validKlarnaCountry = $this->checkValidKlarnaCountry($postedCountry);
1371
            if (!$validKlarnaCountry) {
1372
                $action->redirect(array('controller' => 'payment_klarna', 'action' => 'otherPayment'));
1373
                return;
1374
            }
1375
            if ($shopCountryId !== (int) $postedCountry){
1376
                if ($this->isKlarnaUser()){
1377
                    if ($postedCountry == '23'){
1378
                        $session['sCountry'] = '23';
1379
                        
1380
                    } else { 
1381
                    $action->redirect(array('controller' => 'payment_klarna', 'action' => 'otherPayment'));
1382
                    }
1383
                } else {
1384
                    $action->redirect(array('controller' => 'checkout', 'action' => 'shippingPayment'));
1385
                }
1386
                return;
1387
            }
1388
            
1389
        }
1390
              
1391
        $user = $view->getAssign('sUserData');
1392
1393
        if ($request->getControllerName() == 'checkout' || $request->getControllerName() == 'account') {
1394
            $this->registerMyTemplateDir();
1395
        }
1396
1397
        $config = $this->Config();
1398
1399
        if ($request->getControllerName() == 'checkout'
1400
            && ($request->getActionName() == 'cart' || $request->getActionName() == 'ajaxCart')
1401
        ) {
1402
            $view->assign('KlarnaEnableButton', (bool)$config->get('showKlarnaButton'));
1403
            $view->assign('KlarnaShowCheckoutButton', $this->getShowCheckoutButton($user));
1404
            $view->assign('klarnaKcoPaymentActive', $this->isKlarnaKcoPaymentActive($user));
1405
            $view->assign('KlarnaPaymentDescription', $this->getPayment()->getDescription());
1406
            if (!$this->isTemplateResponsive()) {
1407
                $view->extendsTemplate('frontend/payment_klarna_checkout/cart.tpl');
1408
            }
1409
        }
1410
1411
        if (!empty($config->partPaymentWidget)
1412
            && $request->getControllerName() == 'detail' && $request->getActionName() == 'index'
1413
        ) {
1414
            $this->registerMyTemplateDir();
1415
            //Do not shot the logo on the detail page if the kpm-plugin is active
1416
            $view->KlarnaShowLogo = !$this->isKpmActive();
1417
            $view->KlarnaLocale = $this->getLocale();
1418
            $view->KlarnaMerchantId = $config->get('merchantId');
1419
            if (!$this->isTemplateResponsive()) {
1420
                $view->extendsTemplate('frontend/payment_klarna_part/detail.tpl');
1421
            }
1422
        }
1423
1424
        if (!empty($config->noAccountCheckout)
1425
            && $request->getControllerName() == 'register'
1426
            && $request->getActionName() == 'index'
1427
        ) {
1428
            if ($request->getParam('skipLogin') !== null || $this->isTemplateResponsive()) {
1429
                $payments = $view->register->payment->payment_means;
1430
                foreach ($payments as $payment) {
1431
                    if ($payment['name'] == 'klarna_checkout' && !empty($session['sBasketQuantity'])) {
1432
                        if (empty($session['sPaymentID']) || $payment['id'] == $session['sPaymentID']) {
1433
                            $session['sPaymentID'] = $payment['id'];
1434
                            $action->redirect(array('controller' => 'payment_klarna', 'action' => 'express'));
1435
                            return;
1436
                        }
1437
                    }
1438
                }
1439
            }
1440
        }
1441
1442 View Code Duplication
        if ($request->getControllerName() == 'register' && $request->getActionName() == 'index') {
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...
1443
            $this->registerMyTemplateDir();
1444
            $view->assign('KlarnaLocale', $this->getLocale());
1445
            $view->assign('KlarnaMerchantId', $config->get('merchantId'));
1446
            $view->assign('KlarnaHideCheckoutSteps', true);
1447
            if (!$this->isTemplateResponsive()) {
1448
                $view->extendsTemplate('frontend/payment_klarna_checkout/register.tpl');
1449
            }
1450
        }
1451
1452 View Code Duplication
        if ($request->getControllerName() == 'account' && $request->getActionName() == 'ajax_login') {
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...
1453
            $this->registerMyTemplateDir();
1454
            $view->assign('KlarnaLocale', $this->getLocale());
1455
            $view->assign('KlarnaMerchantId', $config->get('merchantId'));
1456
            if (!$this->isTemplateResponsive()) {
1457
                $view->extendsTemplate('frontend/payment_klarna_checkout/ajax_login.tpl');
1458
            }
1459
        }
1460
1461
        if ($request->getControllerName() == 'checkout' && $request->getActionName() == 'shippingPayment') {
1462
            $this->registerMyTemplateDir();
1463
            $view->assign('KlarnaMerchantId', $config->get('merchantId'));
1464
            $view->assign('KlarnaLocale', $this->getLocale(true));
1465
        }
1466
        
1467
        if (isset($postedCountry) && isset($validKlarnaCountry) && $validKlarnaCountry) {
1468
            $session['sChangedCountry'] = $postedCountry;
1469
        }
1470
        
1471
        if ($controllerName == 'checkout' && $actionName == 'changeQuantity' && $this->isKlarnaKcoPaymentActive($user) && $isFromKCO) {
1472
            $action->redirect(array('controller' => 'payment_klarna', 'action' => 'express'));
1473
        }
1474
        
1475
    }
1476
    
1477
    /**
1478
     * @param Enlight_Event_EventArgs $args
1479
     * @throws Exception
1480
     */
1481
    public function onPostDispatchCheckout($args)
1482
    {
1483
        /** @var $action Enlight_Controller_Action */
1484
        $action = $args->getSubject();
1485
        $request = $action->Request();
1486
        $response = $action->Response();
1487
        $view = $action->View();
1488
1489 View Code Duplication
        if (!$request->isDispatched()
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...
1490
            || $response->isException()
1491
            || $response->isRedirect()
1492
            || $request->getActionName() != 'confirm'
1493
        ) {
1494
            return;
1495
        }
1496
1497
        $connector = $this->getConnector();
1498
        $session = $this->Application()->Session();
1499
        $user = $view->sUserData;
1500
        $basket = $view->sBasket;
1501
        $payment = $view->sPayment;
1502
        /** @var \Shopware\Models\Shop\Shop $shop */
1503
        $shop = $this->Application()->Shop();
1504
        $config = $this->Config();
1505
1506
        $this->registerMyTemplateDir();
1507
        if (!$this->isTemplateResponsive()) {
1508
            $view->extendsTemplate('frontend/payment_klarna_checkout/confirm.tpl');
1509
        }
1510
1511
        if (empty($payment) || $payment['name'] != 'klarna_checkout') {
1512
            return;
1513
        }
1514
1515
        // SwagDhl fix
1516
        $allowPackstation = true;
1517
        if (!empty($view->dhlDispatchIds)) {
1518
            $allowPackstation = false;
1519
            if (in_array($session->sDispatch, $view->dhlDispatchIds)) {
1520
                $allowPackstation = true;
1521
            }
1522
            unset($view->dhlDispatchIds);
1523
        }
1524
1525
        $this->getViewConfig($view, $config);
1526
        
1527
        $preFill = $request->get('klarnaPreFill') || !empty($session['klarnaPreFill']) || $config->get('preFillCheckout');
1528
1529
        try {
1530
            if (isset($session['KlarnaOrder']) && $preFill) {
1531
                $order = new Klarna_Checkout_Order($connector, $session['KlarnaOrder']);
0 ignored issues
show
Documentation introduced by
$connector is of type object<Klarna_Checkout_Connector>, but the function expects a object<Klarna_Checkout_ConnectorInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1532
                $order->fetch();
1533
1534
                if ($order['status'] == "checkout_incomplete") {
1535
                    $update = array();
1536
                    $update['cart']['items'] = $this->getCheckoutCart($basket);
1537
                    $update['options'] = $this->getCheckoutOptions($allowPackstation, $view->sDispatch);
1538
                    if ($request->get('klarnaPreFill') == "on"){
1539
                        $update['customer'] = $this->getCheckoutCustomer($user);
1540
                        if  ( !isset($user['billingaddress']['phone'])) {
1541
                                $user['billingaddress']['phone'] = " ";
1542
                        }  
1543
                        if  ( !isset($user['shippinggaddress']['phone'])) {
1544
                                $user['shippingaddress']['phone'] = " ";
1545
                        }                        
1546 View Code Duplication
                        if ($user['additional']['countryShipping']['id'] == $user['additional']['country']['id']) {
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...
1547
                            $update['shipping_address'] = $this->getCheckoutAddress($user, 'billing');
1548
                        } else {
1549
                            $update['shipping_address'] = $this->getCheckoutAddress($user, 'shipping');
1550
                        }                          
1551
                    }
1552
                    $order->update($update);
1553
                } else {
1554
                    unset($session['KlarnaOrder']);
1555
                }
1556
            } else {
1557
                $create = array();
1558
                $create['cart']['items'] = $this->getCheckoutCart($basket);
1559
                $create['merchant'] = $this->getCheckoutMerchant();
1560
1561
                if (isset($session['sChangedCountry'])) {
1562
                    $session['sCountry'] = $session['sChangedCountry'];
1563
                } else {
1564
                    $session['sCountry'] = $this->getCountryByShop($shop);
1565
                }                
1566
                
1567
                $create['purchase_country'] = $this->getCountryIsoById($session['sCountry']);
1568
                $create['purchase_currency'] = $shop->getCurrency()->toString();
1569
                $create['locale'] = $this->getLocale(false, $create['purchase_country']);
1570
                $create['options'] = $this->getCheckoutOptions($allowPackstation, $view->sDispatch);
1571
1572
                if ($config->get('KlarnaExternalPayments')) {
1573
                    list($create['external_payment_methods'], $create['external_checkouts']) = $this->getExternalPaymentMethods($basket);
1574
                }
1575
1576
                if ($config->get('disableAutofocus')) {
1577
                    $create['gui']['options'] = array('disable_autofocus');
1578
                }
1579
1580
                if (Shopware::VERSION === '___VERSION___' || version_compare(Shopware::VERSION, '5.2.0', '>=')) {
1581
                   if  ( isset($user['additional']['user']['birthday']) && $user['additional']['user']['birthday'] !== "0000-00-00") {
1582
                       $user['billingaddress']['birthday'] = $user['additional']['user']['birthday'];
1583
                       $user['birthday'] = $user['additional']['user']['birthday'];
1584
                   }
1585
                }              
1586
                if  ( !isset($user['billingaddress']['phone'])) {
1587
                        $user['billingaddress']['phone'] = " ";
1588
                }        
1589
1590
                if ($preFill) {
1591
                    $session['klarnaPreFill'] = true;
1592
                    if (empty($session['sCountry'])) {
1593
                        $countryId = $this->getCountryByShop($shop);
1594
                    }
1595
                    else {
1596
                        $countryId = $session['sCountry'];
1597
                    }
1598
                    if ($user['additional']['countryShipping']['id'] == $countryId
1599
                        && $user['billingaddress']['zipcode'] != '00000'
1600
                    ) {
1601
                        $create['customer'] = $this->getCheckoutCustomer($user);
1602 View Code Duplication
                        if ($user['additional']['countryShipping']['id'] == $user['additional']['country']['id']) {
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...
1603
                            $create['shipping_address'] = $this->getCheckoutAddress($user, 'billing');
1604
                        } else {
1605
                            $create['shipping_address'] = $this->getCheckoutAddress($user, 'shipping');
1606
                        }
1607
                    }                    
1608
                } else {
1609
                    $session['klarnaPreFill'] = false;
1610
                }
1611
                $order = new Klarna_Checkout_Order($connector);
0 ignored issues
show
Documentation introduced by
$connector is of type object<Klarna_Checkout_Connector>, but the function expects a object<Klarna_Checkout_ConnectorInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1612
                if ($create['purchase_country'] == 'AT') {
1613
                    $locale = 'de-at';
1614
                } elseif ($create['purchase_country'] == 'DE')
1615
                    {
1616
                     $locale = 'de-de';
1617
                } else {
1618
                    $locale = $this->getLocale(false, $create['purchase_country']);
1619
                }
1620
                $create['locale'] = $locale;
1621
                $order->create($create);
1622
                $order->fetch();
1623
1624
                $session['KlarnaOrder'] = $order->getLocation();
1625
            }
1626
        } catch (Exception $e) {
1627
            unset($session['KlarnaOrder']);
1628
            /** @var Shopware\Components\Logger $logger */
1629
            $logger = $this->get('corelogger');
1630
            $logger->error($e->getMessage());
1631
            Shopware()->Plugins()->Controller()->ViewRenderer()->setNoRender();
1632
            echo "Entschuldigung, Ein Verbindungsfehler ist aufgetreten, bitte aktualisieren Sie die Seite";
1633
        }
1634
1635
        if (isset($session['klarnaSavedRegister'])) {
1636
            try {
1637
                $update = $this->klarnaMapping($session['klarnaSavedRegister']);
1638
                if ($update) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $update 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...
1639
                    $order->update($update);
0 ignored issues
show
Bug introduced by
The variable $order does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1640
                }
1641
            } catch (Exception $e) {
1642
                Shopware()->Plugins()->Controller()->ViewRenderer()->setNoRender();
1643
                echo "Entschuldigung, Ein Verbindungsfehler ist aufgetreten, bitte aktualisieren Sie die Seite";
1644
            }
1645
            unset($session['klarnaSavedRegister']);
1646
        }
1647
        
1648
        if (isset($session['sChangedCountry'])) {
1649
            $sCountryId = $session['sChangedCountry'];
1650
        } else {
1651
            $sCountryId = $this->getCountryByShop($shop);
1652
        }
1653
              
1654
        $view->assign('sCountryId', $sCountryId);
1655
        $view->assign('KlarnaMerchantId', $config->get('merchantId'));
1656
        $view->assign('KlarnaPreFillSelect', !$this->isKlarnaUser() && empty($session['klarnaPreFill']));
1657
        $view->assign('KlarnaLocale', $this->getLocale(true));
1658
        $view->assign('KlarnaOrder', $order->marshal());
1659
    }
1660
1661
    /**
1662
     * Populate register form with saved data on changing klarna and register tabs
1663
     *
1664
     * @param Enlight_Event_EventArgs $args
1665
     */
1666
    public function onPostDispatchFrontendRegister($args)
1667
    {
1668
        /** @var $action Enlight_Controller_Action */
1669
        $action = $args->getSubject();
1670
        $view = $action->View();
1671
        $request = $action->Request();
1672
        /** @var Enlight_Components_Session_Namespace $session */
1673
        $session = $this->Application()->Session();
1674
        $connector = $this->getConnector();
1675
        $controllerName = $request->getControllerName();
0 ignored issues
show
Unused Code introduced by
$controllerName is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1676
        
1677
        if (isset($session['KlarnaOrder'])) {
1678
            $order = new Klarna_Checkout_Order($connector, $session['KlarnaOrder']);
0 ignored issues
show
Documentation introduced by
$connector is of type object<Klarna_Checkout_Connector>, but the function expects a object<Klarna_Checkout_ConnectorInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1679
            
1680
            try {
1681
                $order->fetch();
1682
            } catch (Exception $e) {
1683
                Shopware()->Plugins()->Controller()->ViewRenderer()->setNoRender();
1684
                echo "Entschuldigung, Ein Verbindungsfehler ist aufgetreten, bitte aktualisieren Sie die Seite";
1685
            }
1686
1687
            $registerData = $this->getKlarnaCustomerData($order);
1688 View Code Duplication
            foreach ($registerData['personal'] as $key => $val) {
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...
1689
                if (empty($view->register->personal->form_data->$key)) {
1690
                    $view->register->personal->form_data->$key = trim($val);
1691
                }
1692
            }
1693
1694 View Code Duplication
            foreach ($registerData['billing'] as $key => $val) {
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...
1695
                if (empty($view->register->billing->form_data->$key)) {
1696
                    $view->register->billing->form_data->$key = trim($val);
1697
                }
1698
            }
1699
1700 View Code Duplication
            foreach ($registerData['shipping'] as $key => $val) {
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...
1701
                if (empty($view->register->shipping->form_data->$key)) {
1702
                    $view->register->shipping->form_data->$key = trim($val);
1703
                }
1704
            }
1705
        }
1706
1707
        $view->assign('klarnaRedirect', $request->has('klarnaRedirect') && $request->getParam('klarnaRedirect') == 1);
1708
    }
1709
1710
    public function addJsFiles()
1711
    {
1712
        $jsPath = array(
1713
            __DIR__ . '/Views/responsive/frontend/_public/src/js/jquery.klarna_checkout.js'
1714
        );
1715
1716
        return new Doctrine\Common\Collections\ArrayCollection($jsPath);
1717
    }
1718
1719
    /**
1720
     * @param Enlight_Event_EventArgs $args
1721
     */
1722
    public function onPreDispatchCheckout($args)
1723
    {
1724
        /** @var $action Enlight_Controller_Action */
1725
        $action = $args->getSubject();
1726
        $request = $action->Request();
1727
        $response = $action->Response();
1728
        $view = $action->View();
1729
        $session = $this->Application()->Session();
1730
1731
        if (!$request->isDispatched()
1732
            || $response->isException()
1733
            || $request->getModuleName() != 'frontend'
1734
        ) {
1735
            return;
1736
        }
1737
1738
        if (!isset($session['sCountry'])) {
1739
            $shop = $this->Application()->Shop();
1740
            $session['sCountry'] = $this->getCountryByShop($shop);
1741
        }
1742
1743
        if ($request->getActionName() != 'finish' || !isset($session['KlarnaOrder'])) {
1744
            return;
1745
        }
1746
1747
        $connector = $this->getConnector();
1748
        $order = new Klarna_Checkout_Order($connector, $session['KlarnaOrder']);
0 ignored issues
show
Documentation introduced by
$connector is of type object<Klarna_Checkout_Connector>, but the function expects a object<Klarna_Checkout_ConnectorInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1749
        try {
1750
            $order->fetch();
1751
        } catch (Exception $e) {
1752
            Shopware()->Plugins()->Controller()->ViewRenderer()->setNoRender();
1753
            echo "Entschuldigung, Ein Verbindungsfehler ist aufgetreten, bitte aktualisieren Sie die Seite";
1754
            $this->klarnaLog("Verbindungsfehler in onPreDispatchCheckout\nCode:".$e->getCode()."Nachricht:\n".$e->getMessage(),1);
1755
        }
1756
        
1757
        if ($order['status'] != 'created' && $order['status'] != 'checkout_complete') {
1758
            return;
1759
        }
1760
1761
        $this->registerMyTemplateDir();
1762
        if (!$this->isTemplateResponsive()) {
1763
            $view->extendsTemplate('frontend/payment_klarna_checkout/finish.tpl');
1764
        }
1765
        $view->assign('KlarnaOrder', $order->marshal());
1766
        
1767
        try {
1768
            $data['status'] = 'created';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1769
            $this->klarnaLog("onPreDispatchCheckout: Trying to update order to klarna with state created with following data:",4, $data);
1770
            $order->update($data);
1771
        } catch (Klarna_Checkout_ConnectionErrorException $e) {
1772
            $view->assign('KlarnaConnectionError', json_decode($e->getMessage(), true));
1773
        }       
1774
        unset($session['KlarnaOrder']);
1775
        
1776
        
1777
        $postedCountry = $request->getParam('sCountry');
1778
        if ($postedCountry && !isset($session['sCountry'])) {
1779
            $session['sCountry'] = $postedCountry;   
1780
        }
1781
    }
1782
    
1783
    /**
1784
     * @param Enlight_Event_EventArgs $args
1785
     */
1786 View Code Duplication
    public function onLoadOrderBackendModule(Enlight_Event_EventArgs $args)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1787
    {
1788
        /** @var $subject Enlight_Controller_Action */
1789
        $subject = $args->getSubject();
1790
        $request = $subject->Request();
1791
        $view = $subject->View();
1792
1793
        switch ($request->getActionName()) {
1794
            case 'load':
1795
                $this->registerMyTemplateDir(true);
1796
                $view->extendsTemplate('backend/order/payment_klarna.js');
1797
                break;
1798
            default:
1799
                break;
1800
        }
1801
    }
1802
1803
    /**
1804
     * @param Enlight_Event_EventArgs $args
1805
     */
1806 View Code Duplication
    public function onLoadPaymentBackendModule(Enlight_Event_EventArgs $args)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1807
    {
1808
        /** @var $subject Enlight_Controller_Action */
1809
        $subject = $args->getSubject();
1810
        $request = $subject->Request();
1811
        $view = $subject->View();
1812
1813
        switch ($request->getActionName()) {
1814
            case 'load':
1815
                $this->registerMyTemplateDir(true);
1816
                $view->extendsTemplate('backend/payment/payment_klarna.js');
1817
                break;
1818
            default:
1819
                break;
1820
        }
1821
    }
1822
1823
    public function updateOrderVariables()
1824
    {
1825
        $session = Shopware()->Session();
1826
        $admin = Shopware()->Modules()->Admin();
1827
        /** @var ArrayObject $orderVariables */
1828
        $orderVariables = $session['sOrderVariables'];
1829
        $userData = $admin->sGetUserData();
1830
        $userData['payment'] = $orderVariables['sUserData']['payment'];
1831
        $userData['additional'] = array_merge(
1832
            $orderVariables['sUserData']['additional'],
1833
            $userData['additional']
1834
        );
1835
        
1836
        if (isset($session['sChangedCountry'])){
1837
            
1838
            /** @var \Shopware\Components\Model\ModelManager $em */
1839
            $em = $this->get('models');
1840
1841
            /** @var \Shopware\Models\Customer\Customer $customer */
1842
            $country = $em->getRepository('Shopware\Models\Country\Country')->findOneBy(array('id' => $session['sChangedCountry']));            
1843
            $userData['shippingaddress']['country'] =$country;     
1844
            $userData['billingaddress']['country'] =$country;   
1845
            $userData['shippingaddress']['countryID'] = $session['sChangedCountry'];
1846
            $userData['billingaddress']['countryID'] = $session['sChangedCountry'];
1847
         }
1848
        
1849
        $orderVariables['sUserData'] = $userData;
1850
    }
1851
1852
    /**
1853
     * @param $shop Shopware\Models\Shop\Shop
1854
     * @return int|null
1855
     */
1856
    public function getCountryByShop($shop)
1857
    {
1858
        $locale = $shop->getLocale()->getLocale();
1859
        $this->klarnaLog("Entering Bootstrap::getCountryByShop", 3);
1860
        $locale = explode('_', $locale);
1861
        $locale = isset($locale[1]) ? $locale[1] : $locale[0];
1862
        $this->klarnaLog("Bootstrap::getCountryByShop locale to request for:".$locale,3);
1863
        $sql = 'SELECT id FROM s_core_countries WHERE countryiso=?';
1864
        $countryId = Shopware()->Db()->fetchOne($sql, array($locale));
1865
        $countryId = ($countryId) ? (int)$countryId : null;
1866
                
1867
        return $countryId;
1868
    }
1869
1870
    /**
1871
     * Get user country by country id
1872
     *
1873
     * @param $id
1874
     * @return string
1875
     */
1876
    public function getCountryIsoById($id)
1877
    {
1878
        $sql = 'SELECT countryiso FROM s_core_countries WHERE id = ?';
1879
        $countryIso = Shopware()->Db()->fetchOne($sql, array($id));
1880
1881
        return $countryIso;
1882
    }
1883
1884
    public function getLocale($underscore = false, $countryIso = null)
1885
    {
1886
        /** @var \Shopware\Models\Shop\Shop $shop */
1887
        $shop = $this->Application()->Shop();
1888
        $locale = $shop->getLocale()->getLocale();
1889
        $locale = strtolower($locale);
1890
        if (!$underscore) {
1891
            $locale = str_replace('_', '-', $locale);
1892
        }
1893
        $locale = $locale == 'nn-no' ? 'nb-no' : $locale;
1894
1895
        if ($locale == 'de-de') {
1896
            if($countryIso == 'CH') {
1897
                $locale = 'de-ch';
1898
            } elseif ($countryIso == 'AT') {
1899
                $locale = 'de-at';
1900
            }
1901
        }
1902
1903
        return $locale;
1904
    }
1905
1906
    protected function getCheckoutOptions($allowPackstation = true, $dispatch = array())
1907
    {
1908
        $config = $this->Config();
1909
        $options = $this->getColorConfigOptions($config);
1910
1911
        $options['allow_separate_shipping_address'] = (bool)$config->get('allowSeparateShippingAddress');
1912
        $options['packstation_enabled'] = (bool)$config->get('supportPackstation') && $allowPackstation;
1913
        $options['phone_mandatory'] = (bool)$config->get('mandatoryPhone');
1914
        $options['date_of_birth_mandatory'] = (bool)$config->get('mandatoryBirthday');
1915
1916
        if (!empty($dispatch)) {
1917
            $options['shipping_details'] = $dispatch['description'];
1918
        }
1919
1920
        return $options;
1921
    }
1922
1923
    protected function getCheckoutCart($basket)
1924
    {
1925
        $cart = array();
1926
        foreach ($basket['content'] as $basketItem) {
1927
            $unitPrice = round(str_replace(',', '.', $basketItem['price']) * 100);
1928
            $cart[] = array(
1929
                'type' => $unitPrice >= 0 ? 'physical' : 'discount',
1930
                'reference' => $basketItem['ordernumber'],
1931
                'name' => $basketItem['articlename'],
1932
                'quantity' => (int)$basketItem['quantity'],
1933
                'unit_price' => (int)$unitPrice,
1934
                'tax_rate' => (int)round($basketItem['tax_rate'] * 100)
1935
            );
1936
        }
1937
        if (!empty($basket['sShippingcosts'])) {
1938
            $shippingCostsWithTax = $basket['sShippingcostsWithTax'];
1939
            $shippingAmount = !empty($shippingCostsWithTax) ? $shippingCostsWithTax : $basket['sShippingcosts'];
1940
            $cart[] = array(
1941
                'type' => 'shipping_fee',
1942
                'reference' => 'SHIPPING',
1943
                'name' => 'Shipping Fee',
1944
                'quantity' => 1,
1945
                'unit_price' => (int)round($shippingAmount * 100),
1946
                'tax_rate' => (int)round($basket['sShippingcostsTax'] * 100),
1947
            );
1948
        }
1949
1950
        return $cart;
1951
    }
1952
1953
    protected function getCheckoutMerchant()
1954
    {
1955
        /** @var \Shopware\Components\Routing\RouterInterface $router */
1956
        $router = $this->Application()->Front()->Router();
1957
        $merchant = array();
1958
        $merchant['id'] = $this->Config()->get('merchantId');
1959
        $merchant['terms_uri'] = $router->assemble(
1960
            array(
1961
                'controller' => 'custom',
1962
                'sCustom' => $this->Config()->get('termSiteId', 4),
1963
                'forceSecure' => true
1964
            )
1965
        );
1966
        $merchant['checkout_uri'] = $router->assemble(
1967
            array(
1968
                'action' => 'confirm'
1969
            )
1970
        );
1971
        $merchant['confirmation_uri'] = $router->assemble(
1972
            array(
1973
                'controller' => 'payment_klarna',
1974
                'action' => 'return',
1975
                'forceSecure' => true
1976
            )
1977
        ) . "?transactionId={checkout.order.uri}";
1978
        $merchant['push_uri'] = $router->assemble(
1979
            array(
1980
                'controller' => 'payment_klarna',
1981
                'action' => 'push',
1982
                'forceSecure' => true,
1983
                'appendSession' => true
1984
            )
1985
        ) . "&transactionId={checkout.order.uri}";
1986
        $merchant['back_to_store_uri'] = $router->assemble(
1987
            array(
1988
                'controller' => 'index',
1989
                'action' => 'index'
1990
            )
1991
        );
1992
1993
        return $merchant;
1994
    }
1995
1996
    public function getCheckoutAddress($user, $type = 'billing')
1997
    {
1998
        if (empty($user[$type . 'address']['zipcode']) || $user[$type . 'address']['zipcode'] == '00000') {
1999
            return array();
2000
        }
2001
2002
        $address = array(
2003
            'given_name' => $user[$type . 'address']['firstname'],
2004
            'family_name' => $user[$type . 'address']['lastname'],
2005
            'postal_code' => $user[$type . 'address']['zipcode'],
2006
            'city' => $user[$type . 'address']['city'],
2007
            'country' => $user['additional'][$type == 'billing' ? 'country' : 'countryShipping']['countryiso'],
2008
            'email' => $user['additional']['user']['email'],
2009
            'phone' => $user['billingaddress']['phone'],
2010
        );
2011
        $address['country'] = strtolower($address['country']);
2012
        if ($address['country'] == 'de' || $address['country'] == 'nl') {
2013
            $address['title'] = $user[$type . 'address']['salutation'] == 'ms' ? 'Frau' : 'Herr';
2014
            if ($this->assertMinimumVersion('5.0.0')) {
2015
                /** @var StreetSplitService $streetSplitService */
2016
                $streetSplitService = Shopware()->StreetSplitService();
2017
                $streetAndNumber = $streetSplitService->split($user[$type . 'address']['street']);
2018
2019
                $address['street_name'] = $streetAndNumber['streetName'];
2020
                $address['street_number'] = $streetAndNumber['streetNumber'];
2021 View Code Duplication
            } else {
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...
2022
                $address['street_name'] = $user[$type . 'address']['street'];
2023
                $address['street_number'] = $user[$type . 'address']['streetnumber'];
2024
            }
2025 View Code Duplication
        } else {
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...
2026
            $address['street_address'] = trim(
2027
                $user[$type . 'address']['street'] . ' ' . $user[$type . 'address']['streetnumber']
2028
            );
2029
        }
2030
2031
        return $address;
2032
    }
2033
2034
    public function getCheckoutCustomer($user)
2035
    {
2036
        $customer = array(
2037
            'type' => 'person'
2038
        );
2039
        if (!empty($user['billingaddress']['birthday']) && $user['billingaddress']['birthday'] != '0000-00-00') {
2040
            $customer['date_of_birth'] = $user['billingaddress']['birthday'];
2041
        }
2042
        // SW 5.2 and newer
2043
        if (!empty($user['birthday']) && $user['birthday'] != '0000-00-00') {
2044
            $customer['date_of_birth'] = $user['birthday'];
2045
        }
2046
2047
        return $customer;
2048
    }
2049
2050
    /**
2051
     *
2052
     * @return array
2053
     */
2054
    public function getLabel()
2055
    {
2056
        return 'Klarna Checkout';
2057
    }
2058
2059
    /**
2060
     * @return string
2061
     * @throws Exception
2062
     */
2063
    public function getVersion()
2064
    {
2065
        $info = json_decode(file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'plugin.json'), true);
2066
2067
        if ($info) {
2068
            return $info['currentVersion'];
2069
        } else {
2070
            throw new Exception('The plugin has an invalid version file.');
2071
        }
2072
    }
2073
2074
    /**
2075
     * @return array
2076
     */
2077
    public function getInfo()
2078
    {
2079
        return array(
2080
            'version' => $this->getVersion(),
2081
            'label' => $this->getLabel(),
2082
            'description' => file_get_contents(__DIR__ . '/info.txt')
2083
        );
2084
    }
2085
2086
    /**
2087
     * Creates and returns the klarna client for an event.
2088
     *
2089
     * @return \Klarna_Checkout_Connector
2090
     */
2091
    public function onInitResourceKlarnaCheckoutConnector()
2092
    {
2093
        require_once __DIR__ . '/Components/KlarnaCheckout/Checkout.php';
2094
        if ($this->Config()->get('testDrive')) {
2095
            Klarna_Checkout_Order::$baseUri = 'https://checkout.testdrive.klarna.com/checkout/orders';
2096
        } else {
2097
            Klarna_Checkout_Order::$baseUri = 'https://checkout.klarna.com/checkout/orders';
2098
        }
2099
        Klarna_Checkout_Order::$contentType = "application/vnd.klarna.checkout.aggregated-order-v2+json";
2100
        $sharedSecret = $this->Config()->get('sharedSecret');
2101
        $connector = Klarna_Checkout_Connector::create($sharedSecret);
2102
        $this->klarnaLog("Created Klarna Connector:", 4, $connector);
2103
2104
        return $connector;
2105
    }
2106
2107
    /**
2108
     * @return Klarna
2109
     */
2110
    public function onInitResourceKlarnaService()
2111
    {
2112
        require_once __DIR__ . '/Components/Klarna/Klarna.php';
2113
        require_once __DIR__ . '/Components/Klarna/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
2114
2115
        $k = new Klarna();
2116
        return $k;
2117
    }
2118
2119
    /**
2120
     * Provide the file collection for less
2121
     *
2122
     * @return \Doctrine\Common\Collections\ArrayCollection
2123
     */
2124
    public function addLessFiles()
2125
    {
2126
        $less = new \Shopware\Components\Theme\LessDefinition(
2127
            //configuration
2128
            array(),
2129
            //less files to compile
2130
            array(
2131
                __DIR__ . '/Views/responsive/frontend/_public/src/less/all.less'
2132
            ),
2133
            //import directory
2134
            __DIR__
2135
        );
2136
2137
        return new Doctrine\Common\Collections\ArrayCollection(array($less));
2138
    }
2139
2140
    /**
2141
     * @param string $requiredVersion
2142
     * @return bool|mixed
2143
     */
2144
    protected function assertMinimumVersion($requiredVersion)
2145
    {
2146
        if (Shopware::VERSION === '___VERSION___') {
2147
            return true;
2148
        }
2149
2150
        return version_compare(Shopware::VERSION, $requiredVersion, '>=');
2151
    }
2152
2153
    /**
2154
     * @param Enlight_Event_EventArgs $args
2155
     * @return bool
2156
     */
2157
    public function onCheckoutSaveShippingKlarna(Enlight_Event_EventArgs $args)
2158
    {
2159
        /** @var Shopware_Controllers_Frontend_Checkout $controller */
2160
        $controller = $args->getSubject();
2161
        if (!$controller->Request()->isPost()) {
2162
            $controller->forward('shippingPayment');
2163
            return true;
2164
        }
2165
2166
        // Save payment and shipping method data.
2167
        $controller->setDispatch($controller->Request()->getPost('sDispatch'));
2168
        $controller->redirect(array('controller' => 'payment_klarna', 'action' => 'express'));
2169
        return true;
2170
    }
2171
2172
    /**
2173
     * This event is executed when the expressAction of the checkout-controller should be executed.
2174
     * It is needed to redirect the user back to the klarna checkout after deleting an article in the klarna checkout.
2175
     *
2176
     * @param Enlight_Event_EventArgs $args
2177
     * @return bool
2178
     */
2179
    public function onCheckoutExpress(Enlight_Event_EventArgs $args)
2180
    {
2181
        /** @var $action Enlight_Controller_Action */
2182
        $action = $args->getSubject();
2183
2184
        $action->redirect(array('controller' => 'payment_klarna', 'action' => 'express'));
2185
        return true;
2186
    }
2187
2188
    /**
2189
     * Mapping to populate klarna checkout with saved information from register page
2190
     *
2191
     * @param $form
2192
     * @return mixed
2193
     */
2194
    private function klarnaMapping($form)
2195
    {
2196
        $fields = array(
2197
            'email' => 'email',
2198
            'zipcode' => 'postal_code',
2199
            'firstname' => 'given_name',
2200
            'lastname' => 'family_name',
2201
        );
2202
2203
        $create = array();
2204
        foreach ($fields as $formField => $klarnaField) {
2205 View Code Duplication
            if (!empty($form['register']['personal'][$formField])) {
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...
2206
                $create['shipping_address'][$klarnaField] = $form['register']['personal'][$formField];
2207
            }
2208 View Code Duplication
            if (!empty($form['register']['billing'][$formField])) {
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...
2209
                $create['shipping_address'][$klarnaField] = $form['register']['billing'][$formField];
2210
            }
2211
        }
2212
2213
        $countryIso = $this->getCountryIsoById($form['register']['billing']['country']);
2214
2215
        $salutation = $form['register']['personal']['salutation'];
2216
        if (!empty($salutation) && ($countryIso == 'DE' || $countryIso == 'NL')) {
2217
            $create['shipping_address']['title'] = ($salutation == 'ms' ? 'Frau' : 'Herr');//German names
2218
        }
2219
2220
        $billingStreet = $form['register']['billing']['street'];
2221
        $billingStreetNumber = $form['register']['billing']['streetnumber'];
2222
        if (!empty($billingStreet)) {
2223
            if ($countryIso == 'DE' || $countryIso == 'NL') {
2224
                if ($this->assertMinimumVersion('5.0.0')) {
2225
                    preg_match('(^(?P<street>.+)\\s+(?P<number>\\d+\\S*)$)', $billingStreet, $matches);
2226
2227
                    $create['shipping_address']['street_name'] = $matches['street'];
2228
                    $create['shipping_address']['street_number'] = $matches['number'];
2229
                } else {
2230
                    $create['shipping_address']['street_name'] = $form['register']['billing']['street'];
2231
                    $create['shipping_address']['street_number'] = $billingStreetNumber;
2232
                }
2233
            } else {
2234
                $create['shipping_address']['street_address'] = $billingStreet . ' ' . $billingStreetNumber;
2235
            }
2236
        }
2237
2238
        return $create;
2239
    }
2240
2241
    /**
2242
     * Helper method to read the color-config options properly.
2243
     *
2244
     * @param $config Enlight_Config
2245
     * @return mixed
2246
     */
2247
    private function getColorConfigOptions($config)
2248
    {
2249
        $options = array();
2250
        $checkoutButtonColor = $config->get('checkoutButtonColor');
2251
        $checkoutButtonTextColor = $config->get('checkoutButtonTextColor');
2252
        $checkoutCheckboxColor = $config->get('checkoutCheckboxColor');
2253
        $checkoutCheckboxCheckMarkColor = $config->get('checkoutCheckboxCheckmarkColor');
2254
        $checkoutHeaderColor = $config->get('checkoutHeaderColor');
2255
        $checkoutLinkColor = $config->get('checkoutLinkColor');
2256
2257
        if (!empty($checkoutButtonColor) && $checkoutButtonColor !== "#") {
2258
            $options['color_button'] = $checkoutButtonColor;
2259
        }
2260
        if (!empty($checkoutButtonTextColor) && $checkoutButtonTextColor !== "#") {
2261
            $options['color_button_text'] = $checkoutButtonTextColor;
2262
        }
2263
        if (!empty($checkoutCheckboxColor) && $checkoutCheckboxColor !== "#") {
2264
            $options['color_checkbox'] = $checkoutCheckboxColor;
2265
        }
2266
        if (!empty($checkoutCheckboxCheckMarkColor) && $checkoutCheckboxCheckMarkColor !== "#") {
2267
            $options['color_checkbox_checkmark'] = $checkoutCheckboxCheckMarkColor;
2268
        }
2269
        if (!empty($checkoutHeaderColor) && $checkoutHeaderColor !== "#") {
2270
            $options['color_header'] = $checkoutHeaderColor;
2271
        }
2272
        if (!empty($checkoutLinkColor) && $checkoutLinkColor !== "#") {
2273
            $options['color_link'] = $checkoutLinkColor;
2274
        }
2275
2276
        return $options;
2277
    }
2278
2279
    /**
2280
     * @param $view Enlight_View_Default
2281
     * @param $config Enlight_Config
2282
     */
2283
    private function getViewConfig($view, $config)
2284
    {
2285
        /** @var sAdmin $adminModule */
2286
        $adminModule = $this->get('modules')->Admin();
2287
        $session = $this->get('session');
2288
        $sCountry = $session['sCountry'];
0 ignored issues
show
Unused Code introduced by
$sCountry is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2289
        $view->assign('sCountryId', $session['sCountry']);
2290
        $view->assign('sPayments', $this->filterPayments($adminModule->sGetPaymentMeans()));
2291
        $view->assign('sCountryList', $adminModule->sGetCountryList());
2292
        $view->assign('KlarnaHideCheckoutSteps', true);
2293
        $view->assign('KlarnaShowB2bSelect', (bool)$config->get('showB2bSelect'));
2294
        $view->assign('KlarnaShowBasket', (bool)$config->get('showMiniBasket'));
2295
        $view->assign('KlarnaShowDispatch', (bool)$config->get('showDispatch'));
2296
        $view->assign(
2297
            'KlarnaCDNLink',
2298
            $this->buildCDNLink()
2299
        );
2300
        $view->assign(
2301
            'KlarnaLoggedInUser',
2302
            $view->sUserData['billingaddress']['lastname'] == 'Klarna Checkout'
2303
        );
2304
        $view->assign(
2305
            'KlarnaShowLogin',
2306
            $this->getShowLoginConfig($config, $view->sUserData['billingaddress']['lastname'])
2307
        );
2308
        $view->assign(
2309
            'KlarnaDisplayType',
2310
            $this->getKlarnaDisplayType($config)
2311
        );
2312
        $view->assign(
2313
            'KlarnaPositionOrder',
2314
            $this->getPositionOrder($config)
2315
        );
2316
    }
2317
2318
    /**
2319
     * Helper method to get the config whether or not to show the login-panel in the klarna-checkout.
2320
     *
2321
     * @param $config Enlight_Config
2322
     * @param $lastName string
2323
     * @return bool
2324
     */
2325
    private function getShowLoginConfig($config, $lastName)
2326
    {
2327
        return (bool)$config->get('showLoginPanel') && $lastName == 'Klarna Checkout';
2328
    }
2329
2330
    /**
2331
     * Helper method to read all countries.
2332
     * Reads all countries connected to a locale by the iso.
2333
     * Additionally reads out if that country is configured for the klarna-payment method.
2334
     * @example array(
2335
         array(
2336
             'id' => 1,
2337
             'localeId' => 17,
2338
             'countryname' => 'Germany',
2339
             'configured' => 0
2340
         ),
2341
         array(
2342
             'id' => 4,
2343
             'localeId' => 22,
2344
             'countryname' => 'Austria',
2345
             'configured' => 1
2346
         )
2347
     );
2348
     * @return array
2349
     */
2350
    private function getAllCountries()
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
2351
    {
2352
        if (empty($this->countries)) {
2353
            $sql = "SELECT cl.id, cc.id as countryId, cl.territory, cc.countryname, IF(pmc.countryID IS NULL, IF(pmc2.countryID IS NULL, 1, 0), 1) as configured
2354
                FROM s_core_countries cc
2355
                INNER JOIN s_core_locales cl
2356
                    ON cl.locale LIKE CONCAT('%_', cc.countryiso)
2357
                LEFT JOIN s_core_paymentmeans_countries pmc
2358
                    ON cc.id = pmc.countryID
2359
                    AND pmc.paymentID = (SELECT id FROM s_core_paymentmeans WHERE action='payment_klarna')
2360
                LEFT JOIN s_core_paymentmeans_countries pmc2
2361
                    ON pmc2.paymentID = (SELECT id FROM s_core_paymentmeans WHERE action='payment_klarna')
2362
                WHERE cc.active = 1
2363
                GROUP BY cc.countryname
2364
                ORDER BY cc.position, cc.countryname";
2365
2366
            $result = Shopware()->Db()->fetchAssoc($sql, array());
2367
2368
            // Load translations if available
2369
            $this->countries = array_map(function ($country) {
2370
                $country['id'] = $country['countryId'];
2371
                return Shopware()->Modules()->Admin()->sGetCountryTranslation($country);
2372
            }, $result);
2373
        }
2374
2375
        return $this->countries;
2376
    }
2377
2378
    /**
2379
     * Helper method to find the correct display-type for the frontend.
2380
     * Will return the value configured in the plugin-config, if there is at least one more payment-mean besides klarna.
2381
     * @param $config Enlight_Config
2382
     * @return int
2383
     */
2384
    private function getKlarnaDisplayType($config)
2385
    {
2386
        if (!$this->getOtherPayments()) {
2387
            return 2;
2388
        }
2389
        return $config->get('displayType');
2390
    }
2391
2392
    /**
2393
     * Helper method to find other payment-means besides klarna.
2394
     * @return bool
2395
     */
2396
    private function getOtherPayments()
2397
    {
2398
        $payments = $this->Application()->Modules()->Admin()->sGetPaymentMeans();
2399
2400
        foreach ($payments as $payment) {
2401
            if ($payment['action'] != 'payment_klarna') {
2402
                return true;
2403
            }
2404
        }
2405
2406
        return false;
2407
    }
2408
2409
    /**
2410
     * Helper method to figure out whether or not to show the extra klarna checkout button.
2411
     * @return bool
2412
     */
2413
    private function getShowCheckoutButton($user)
2414
    {
2415
        if (!empty($user['additional']['payment']['id']) && $user['additional']['payment']['id'] != $this->getPayment()->getId()) {
2416
            return true;
2417
        }
2418
2419
        return false;
2420
    }
2421
2422
    /**
2423
     * Helper method to get the correct order for the elements
2424
     *
2425
     * @param $config Enlight_Config
2426
     * @return array Array with the order of the elements
2427
     */
2428
    private function getPositionOrder($config)
2429
    {
2430
        $loginPanel = 'login_panel';
2431
        $miniBasket = 'mini_basket';
2432
        $dispatch = 'dispatch';
2433
        $payments = 'payments';
2434
        switch ($config->get('positionOrder')) {
2435
            case 1:
2436
                return array($loginPanel, $miniBasket, $dispatch, $payments);
2437
            case 2:
2438
                return array($loginPanel, $miniBasket, $payments, $dispatch);
2439
            case 3:
2440
                return array($dispatch, $payments, $loginPanel, $miniBasket);
2441
            case 4:
2442
            default:
2443
                return array($payments, $dispatch, $loginPanel, $miniBasket);
2444
        }
2445
    }
2446
2447
    /**
2448
     * Helper method to build the proper cdn-link for the image in the tabs-layout.
2449
     * @return string
2450
     */
2451
    private function buildCDNLink()
2452
    {
2453
        $validLocales = array(
2454
            'de_de',
2455
            'de_at',
2456
            'en_us',
2457
            'en_gb',
2458
            'fi_fi',
2459
            'sv_se',
2460
            'nb_no',
2461
        );
2462
        $locale = str_replace('-', '_', $this->getLocale());
2463
2464
        if (!in_array($locale, $validLocales)) {
2465
            $locale = 'en_gb';
2466
        }
2467
        return "https://cdn.klarna.com/1.0/shared/image/generic/badge/{$locale}/checkout/long-no-klarna-logo.png";
2468
    }
2469
2470
    /**
2471
     * Helper method to read the customer-data from the klarna order-object.
2472
     * @param Klarna_Checkout_Order $order
2473
     * @return array
2474
     */
2475
    private function getKlarnaCustomerData($order)
2476
    {
2477
        $billingAddress = $order['billing_address'];
2478
2479
        return array(
2480
            'personal' => array(
2481
                'customer_type' => 'private',
2482
                'salutation' => $billingAddress['title'],
2483
                'firstname' => $billingAddress['given_name'],
2484
                'lastname' => $billingAddress['family_name'],
2485
                'email' => $billingAddress['email'],
2486
                'birthday' => $order['customer']['date_of_birth'],
2487
                'phone' => $billingAddress['phone']
2488
            ),
2489
            'billing' => array(
2490
                'street' => $billingAddress['street_name'] . ' ' . $billingAddress['street_number'],
2491
                'zipcode' => $billingAddress['postal_code'],
2492
                'city' => $billingAddress['city']
2493
            )
2494
        );
2495
    }
2496
2497
    /**
2498
     * Returns an array with all translations
2499
     * @return array
2500
     */
2501
    private function getTranslationArray()
2502
    {
2503
        return array(
2504
            'en_GB' => array(
2505
                'testDrive' => array(
2506
                    'label' => 'Activate test-modus'
2507
                ),
2508
                'merchantId' => array(
2509
                    'label' => 'API merchant ID (EID)'
2510
                ),
2511
                'sharedSecret' => array(
2512
                    'label' => 'API-Secret (sharedsecret)'
2513
                ),
2514
                'termSiteId' => array(
2515
                    'label' => 'Shopsite including the terms and conditions'
2516
                ),
2517
                'allowSeparateShippingAddress' => array(
2518
                    'label' => 'Enable differing shipping address'
2519
                ),
2520
                'supportPackstation' => array(
2521
                    'label' => 'Support DHL-packstation',
2522
                    'helpText' => 'The differing shipping address must be enabled'
2523
                ),
2524
                'postnumberField' => array(
2525
                    'label' => 'Alternative field for the DHL-postnumber'
2526
                ),
2527
                'mandatoryPhone' => array(
2528
                    'label' => 'Phone mandatory field'
2529
                ),
2530
                'mandatoryBirthday' => array(
2531
                    'label' => 'Birthday mandatory field'
2532
                ),
2533
                'disableAutofocus' => array(
2534
                    'label' => 'Disable auto-focus'
2535
                ),
2536
                'showKlarnaButton' => array(
2537
                    'label' => 'Show klarna-checkout button'
2538
                ),
2539
                'checkoutButtonColor' => array(
2540
                    'label' => 'Checkout Button Color'
2541
                ),
2542
                'checkoutButtonTextColor' => array(
2543
                    'label' => 'Checkout Buttontext Color'
2544
                ),
2545
                'checkoutCheckboxColor' => array(
2546
                    'label' => 'Checkout Checkbox Color'
2547
                ),
2548
                'checkoutCheckboxCheckmarkColor' => array(
2549
                    'label' => 'Checkout Checkbox Tick Color'
2550
                ),
2551
                'checkoutHeaderColor' => array(
2552
                    'label' => 'Checkout Header Color'
2553
                ),
2554
                'checkoutLinkColor' => array(
2555
                    'label' => 'Checkout Link Color'
2556
                ),
2557
                'KlarnaExternalPayments' => array(
2558
                    'label' => 'Display external payment-methods in klarna checkout',
2559
                    'helpText' => 'Your klarna-account has to be unlocked for this feature',
2560
                ),
2561
                'displayType' => array(
2562
                    'label' => 'Klarna Checkout display-type',
2563
                    'store' => array(
2564
                        array(1, 'Display tabs'),
2565
                        array(2, 'Display only klarna checkout'),
2566
                        array(3, 'One-page display')
2567
                    ),
2568
                ),
2569
                'showB2bSelect' => array(
2570
                    'label' => 'Show B2B-select',
2571
                    'helpText' => 'Displays a new select-box containing "Private customer" and "Company" in the klarna checkout'
2572
                ),
2573
                'showLoginPanel' => array(
2574
                    'label' => 'Show login-panel',
2575
                    'helpText' => 'Displays a login-panel in the klarna-checkout',
2576
                ),
2577
                'showMiniBasket' => array(
2578
                    'label' => 'Show mini-basket',
2579
                    'helpText' => 'Displays a small overview of the basket in the klarna-checkout',
2580
                ),
2581
                'showDispatch' => array(
2582
                    'label' => 'Show shipping-country and -method',
2583
                    'helpText' => 'Shows a shipping-country and shipping-method select in the klarna-checkout'
2584
                ),
2585
                'partPaymentWidget' => array(
2586
                    'label' => 'Show partial-payment-widget on detail-page'
2587
                ),
2588
                'convertShippingFee' => array(
2589
                    'label' => 'Convert shipping-costs to an order-position'
2590
                ),
2591
                'statusId' => array(
2592
                    'label' => 'Payment status after order'
2593
                ),
2594
                'activateStatusId' => array(
2595
                    'label' => 'Payment status after activation'
2596
                ),
2597
                'cancelStatusId' => array(
2598
                    'label' => 'Payment status after cancellation'
2599
                )
2600
            )
2601
        );
2602
    }
2603
2604
    /**
2605
     * Helper method to update the klarna-payment when updating from any version to >= 2.0 of klarna.
2606
     * It adds "austria" to the valid countries.
2607
     */
2608
    private function updatePayment()
2609
    {
2610
        /** @var \Shopware\Components\Model\ModelManager $manager */
2611
        $manager = $this->get('models');
2612
        $payment = $manager->getRepository('Shopware\Models\Payment\Payment')->findOneBy(array(
2613
            'name' => 'klarna_checkout'
2614
        ));
2615
2616
        if (empty($payment)) {
2617
            return;
2618
        }
2619
2620
        $updateNeeded = true;
2621
        $countries = $payment->getCountries();
2622
        /** @var Shopware\Models\Country\Country $country */
2623
        foreach ($countries as $country) {
2624
            if ($country->getIso() == 'AT') {
2625
                $updateNeeded = false;
2626
            }
2627
        }
2628
2629
        if ($updateNeeded) {
2630
            $countries->add($manager->getRepository('Shopware\Models\Country\Country')->findOneBy(array('iso' => 'AT')));
2631
            $payment->setCountries($countries);
2632
2633
            $manager->persist($payment);
2634
            $manager->flush();
2635
        }
2636
    }
2637
2638
    /**
2639
     * @return bool
2640
     */
2641
    public function isKlarnaUser()
2642
    {
2643
        $session = $this->get('session');
2644
        if (!$session->offsetGet('sUserId')) {
2645
            return false;
2646
        }
2647
        $email = $session->offsetGet('sUserMail');
2648
        $sessionId = $session->offsetGet('sessionId');
2649
        if (!preg_match('#.{' . strlen($sessionId) . '}@klarna.com#', $email)) {
2650
            return false;
2651
        }
2652
2653
        return true;
2654
    }
2655
2656
    /**
2657
     * Helper method to find and remove all klarna-users older than 24 hours
2658
     */
2659
    public function removeKlarnaUsers()
2660
    {
2661
        $connection = Shopware()->Models()->getConnection();
2662
2663
        $builder = $connection->createQueryBuilder();
2664
        $builder->select('user.id')
2665
            ->from('s_user', 'user')
2666
            ->innerJoin(
2667
                'user',
2668
                's_user_billingaddress',
2669
                'billing',
2670
                'billing.userID = user.id'
2671
            )
2672
            ->where('billing.lastname = :lastName')
2673
            ->andWhere('DATE_SUB(NOW(), INTERVAL 1 DAY) >= user.lastlogin')
2674
            ->setParameter(':lastName', 'Klarna Checkout');
2675
2676
        $ids = array_column($builder->execute()->fetchAll(), 'id');
2677
2678
        if (empty($ids)) {
2679
            return;
2680
        }
2681
2682
        $builder = $connection->createQueryBuilder();
2683
        $builder->delete('s_user')->where('id IN (:ids)')->setParameter(
2684
            'ids',
2685
            $ids,
2686
            Connection::PARAM_INT_ARRAY
2687
        )->execute();
2688
2689
        $builder->delete('s_user_billingaddress')->where('userID IN (:ids)')->setParameter(
2690
            'ids',
2691
            $ids,
2692
            Connection::PARAM_INT_ARRAY
2693
        )->execute();
2694
2695
        $builder->delete('s_user_shippingaddress')->where('userID IN (:ids)')->setParameter(
2696
            'ids',
2697
            $ids,
2698
            Connection::PARAM_INT_ARRAY
2699
        )->execute();
2700
    }
2701
    
2702
    /**
2703
     * Method checks if selected country is valid for use with klarna
2704
     * 
2705
     * @param string $countryId
2706
     * @return boolean
2707
     */
2708
    protected function checkValidKlarnaCountry($countryId) {
2709
        $countries = $this->getPayment()->getCountries();
2710
        foreach ($countries as $country) {
2711
            $allowedCountries[] = $country->getId();
0 ignored issues
show
Coding Style Comprehensibility introduced by
$allowedCountries was never initialized. Although not strictly required by PHP, it is generally a good practice to add $allowedCountries = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
2712
        }
2713
2714
        return in_array($countryId, $allowedCountries);
0 ignored issues
show
Bug introduced by
The variable $allowedCountries does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2715
    }
2716
    
2717
2718
    /**
2719
     * Helper method to read all payments, that should be displayed in the klarna checkout.
2720
     * @param $basket
2721
     * @return array
2722
     */
2723
    private function getExternalPaymentMethods($basket)
2724
    {
2725
        $payments = Shopware()->Models()->getRepository('Shopware\Models\Attribute\Payment')->findBy(array(
2726
            'swagKlarnaShowInKlarnaIframe' => 1,
2727
            'swagKlarnaAllowInPaymentContainer' => 0
2728
        ));
2729
2730
        $externalPayments = array();
2731
        $externalCheckouts = array();
2732
        /** @var Shopware\Models\Attribute\Payment $payment */
2733
        foreach ($payments as $payment) {
2734
            $paymentObj = $payment->getPayment();
2735
            if (is_null($paymentObj)){
2736
                $paymentName = false;
2737
            } else {
2738
                $paymentName = $paymentObj->getName();
2739
            }
2740
            
2741
            if(!$paymentName){
2742
                continue;
2743
            }            
2744
            
2745
            if ($paymentName && $paymentName == 'klarna_checkout') {
2746
                continue;
2747
            }
2748
            $paymentArray = array(
2749
                'name' => $payment->getPayment()->getDescription(),
2750
                'redirect_uri' => $this->getRedirectUri() . '/paymentId/' . $payment->getPaymentId()
2751
            );
2752
2753
            if ($fee = $this->getFee($payment->getPayment(), $basket)) {
2754
                $paymentArray['fee'] = $fee;
2755
            }
2756
2757
            if ($description = $payment->getPayment()->getAdditionalDescription()) {
2758
                //Shorten the description to max. 500 characters
2759
                $description = strip_tags($description);
2760
                $description = preg_replace('#<!--.*-->#ms', '', $description);
2761
                $paymentArray['description'] = substr($description, 0, 497) . '...';
2762
            }
2763
2764
            //Only add to external checkouts if an image is set and if the shop supports SSL
2765
            if (Shopware()->Shop()->getSecure() && $image = $this->getImageForKlarna($payment)) {
2766
                $paymentArray['image_uri'] = $image;
2767
                $externalCheckouts[] = $paymentArray;
2768
            }
2769
2770
            $externalPayments[] = $paymentArray;
2771
        }
2772
2773
        return array($externalPayments, $externalCheckouts);
2774
    }
2775
2776
    /**
2777
     * @param Shopware\Models\Payment\Payment $payment
2778
     * @param $basket
2779
     * @return bool
2780
     */
2781
    private function getFee($payment, $basket)
2782
    {
2783
        $fee = 0;
2784
        $amount = str_replace(',', '.', $basket['Amount']);
2785
2786
        if ($surcharge = $payment->getSurcharge()) {
2787
            $fee += $surcharge;
2788
            $amount += $surcharge;
2789
        }
2790
2791
        if ($percent = $payment->getDebitPercent()) {
2792
            $fee += round($amount / 100 * $percent, 3);
2793
        }
2794
2795
        return round($fee * 100);
2796
    }
2797
2798
    /**
2799
     * Helper method to get the redirect-uri
2800
     * @return string
2801
     */
2802
    private function getRedirectUri()
2803
    {
2804
        return Shopware()->Front()->Router()->assemble(array(
2805
            'controller' => 'PaymentKlarna',
2806
            'action' => 'setPayment'
2807
        ));
2808
    }
2809
2810
    /**
2811
     * Helper method to read the image for the klarna-checkout if set
2812
     * @param Shopware\Models\Attribute\Payment $payment
2813
     * @return null|string
2814
     */
2815
    private function getImageForKlarna($payment)
2816
    {
2817
        $media = $payment->getSwagKlarnaKlarnaMedia();
2818
        if (!$payment->getSwagKlarnaShowInKlarnaIframe() || !empty($media)) {
2819
            if ($this->assertMinimumVersion('5.1') && version_compare(Shopware::VERSION, '5.2.0', '<=') ) {
2820
                $media = $this->get('shopware_media.media_service')->getUrl($media);
2821
            } else {
2822
                /** @var Enlight_Controller_Front $front */
2823
                $front = $this->get('front');
2824
                $request = $front->Request();
2825
                if ($request && $request->getHttpHost()) {
2826
                    $url = ($request->isSecure() ? 'https' : 'http') . '://' . $request->getHttpHost() . $request->getBasePath() . "/";
2827
                } else {
2828
                    $url = $front->Router()->assemble(array('controller' => 'index', 'module' => 'frontend'));
2829
                }
2830
		if (version_compare(Shopware::VERSION, '5.2.0', '>=')) {
2831
			$media = $url . 'media/image/' . $media;
2832
		} else {
2833
	                $media = $url . $media;
2834
		}
2835
            }
2836
2837
            return $media;
2838
        }
2839
        return null;
2840
    }
2841
2842
    /**
2843
     * Helper method to filter the available payment-means.
2844
     * @param $sGetPaymentMeans
2845
     * @return array
2846
     */
2847
    private function filterPayments($sGetPaymentMeans)
2848
    {
2849
        $paymentArray = array();
2850
        foreach ($sGetPaymentMeans as $paymentMean) {
2851
            if (!$this->isPaymentAllowed($paymentMean)) {
2852
                continue;
2853
            }
2854
2855
            $paymentArray[] = $paymentMean;
2856
        }
2857
        return $paymentArray;
2858
    }
2859
2860
    /**
2861
     * Helper method to check if a payment is allowed to be
2862
     * @param $payment
2863
     * @return bool
2864
     */
2865
    private function isPaymentAllowed($payment)
2866
    {
2867
        if ($payment['name'] == 'klarna_checkout') {
2868
            return false;
2869
        }
2870
        $connection = Shopware()->Models()->getConnection();
2871
2872
        $builder = $connection->createQueryBuilder();
2873
        $builder->select('swag_klarna_allow_in_payment_container', 'swag_klarna_show_in_klarna_iframe')
2874
            ->from('s_core_paymentmeans_attributes')
2875
            ->where('paymentmeanID = :id')
2876
            ->setParameter(':id', $payment['id']);
2877
2878
        $result = reset($builder->execute()->fetchAll());
0 ignored issues
show
Bug introduced by
$builder->execute()->fetchAll() cannot be passed to reset() as the parameter $array expects a reference.
Loading history...
2879
        return !$result['swag_klarna_allow_in_payment_container'] && !$result['swag_klarna_show_in_klarna_iframe'];
2880
    }
2881
2882
    /**
2883
     * Builds the new klarna version-string.
2884
     *
2885
     * @param Klarna $klarna
2886
     * @return string
2887
     */
2888
    private function buildKlarnaVersion(Klarna $klarna)
2889
    {
2890
        $versionInfo = array(
2891
            'Shopware',
2892
            $this->Application()->Config()->version,
2893
            'KCO-Plugin',
2894
            $this->getVersion(),
2895
            $klarna->getVersion()
2896
        );
2897
2898
        return implode(':', $versionInfo);
2899
    }
2900
2901
    /**
2902
     * Helper method to find out if the kpm plugin is active
2903
     */
2904
    public function isKpmActive()
2905
    {
2906
        /** @var Doctrine\DBAL\Query\QueryBuilder $queryBuilder */
2907
        $queryBuilder = Shopware()->Models()->getConnection()->createQueryBuilder();
2908
2909
        $result = $queryBuilder->select('plugin.id')
2910
            ->from('s_core_plugins', 'plugin')
2911
            ->where('plugin.name = :name')
2912
            ->andWhere('plugin.active = 1')
2913
            ->setParameter('name', 'SwagPaymentKlarnaKpm')
2914
            ->execute()
2915
            ->fetchColumn();
2916
2917
        return !empty($result);
2918
    }
2919
2920
    /**
2921
     * Helper method to find out if the klarna kco payment is active.
2922
     * Necessary to disable the checkout-button.
2923
     * @param array $user
2924
     * @return bool
2925
     */
2926
    public function isKlarnaKcoPaymentActive($user)
2927
    {
2928
        $payment = $this->getPayment();
2929
        if (!$payment) {
2930
            return false;
2931
        }
2932
        $data = $this->get('modules')->Admin()->sGetPaymentMeanById($payment->getId(), $user);
2933
        if (empty($data) || $data['id'] != $payment->getId()) {
2934
            return false;
2935
        }
2936
        return true;
2937
    }
2938
}
2939