Passed
Pull Request — master (#100)
by Raúl
04:23 queued 02:00
created

Pagantis::hookPayment()   C

Complexity

Conditions 11
Paths 42

Size

Total Lines 74
Code Lines 56

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 56
c 1
b 0
f 0
nc 42
nop 1
dl 0
loc 74
rs 6.8133

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * This file is part of the official Pagantis module for PrestaShop.
4
 *
5
 * @author    Pagantis <[email protected]>
6
 * @copyright 2019 Pagantis
7
 * @license   proprietary
8
 */
9
10
if (!defined('_PS_VERSION_')) {
11
    exit;
12
}
13
14
define('_PS_PAGANTIS_DIR', _PS_MODULE_DIR_. '/pagantis');
15
define('PROMOTIONS_CATEGORY', 'pagantis-promotion-product');
16
define('PROMOTIONS_CATEGORY_NAME', 'Pagantis Promoted Product');
17
18
require _PS_PAGANTIS_DIR.'/vendor/autoload.php';
19
20
/**
21
 * Class Pagantis
22
 */
23
class Pagantis extends PaymentModule
24
{
25
    /**
26
     * @var string
27
     */
28
    public $url = 'https://pagantis.com';
29
30
    /**
31
     * @var bool
32
     */
33
    public $bootstrap = true;
34
35
    /** @var string $language */
36
    public $language;
37
38
    /**
39
     * Default module advanced configuration values
40
     *
41
     * @var array
42
     */
43
    public $defaultConfigs = array(
44
        'URL_OK' => '',
45
        'URL_KO' => '',
46
        'ALLOWED_COUNTRIES' => 'a:3:{i:0;s:2:"es";i:1;s:2:"it";i:2;s:2:"fr";}',
47
        'PRODUCTS' => 'P4X,PAGANTIS',
48
        'P4X' => '{
49
            "CODE": "P4X",
50
            "TITLE": "Pay in 4 installments, without cost",
51
            "SIMULATOR_TITLE": "up to 4 payments of",
52
            "SIMULATOR_SUBTITLE": "without cost with",
53
            "SIMULATOR_DISPLAY_TYPE": "p4x",
54
            "SIMULATOR_DISPLAY_IMAGE": "https://cdn.digitalorigin.com/assets/master/logos/pg-favicon.png",
55
            "SIMULATOR_DISPLAY_TYPE_CHECKOUT": "sdk.simulator.types.CHECKOUT_PAGE",
56
            "SIMULATOR_START_INSTALLMENTS": "4",
57
            "SIMULATOR_CSS_PRICE_SELECTOR": "default",
58
            "SIMULATOR_CSS_QUANTITY_SELECTOR": "default",
59
            "SIMULATOR_CSS_PRODUCT_PAGE_STYLES": "",
60
            "SIMULATOR_CSS_CHECKOUT_PAGE_STYLES": "",
61
            "SIMULATOR_DISPLAY_MAX_AMOUNT": "800",
62
            "FORM_DISPLAY_TYPE" : "0",
63
            "DISPLAY_MIN_AMOUNT": "0",
64
            "DISPLAY_MAX_AMOUNT": "800",
65
            "SIMULATOR_THOUSAND_SEPARATOR": ".",
66
            "SIMULATOR_DECIMAL_SEPARATOR": ","
67
            }',
68
        'PAGANTIS' => '{
69
            "CODE": "PAGANTIS",
70
            "TITLE": "Instant Financing",
71
            "SIMULATOR_TITLE": "Instant Financing",
72
            "SIMULATOR_SUBTITLE": "",
73
            "SIMULATOR_DISPLAY_TYPE": "sdk.simulator.types.PRODUCT_PAGE",
74
            "SIMULATOR_DISPLAY_TYPE_CHECKOUT": "sdk.simulator.types.CHECKOUT_PAGE",
75
            "SIMULATOR_DISPLAY_SKIN": "sdk.simulator.skins.BLUE",
76
            "SIMULATOR_START_INSTALLMENTS": "3",
77
            "SIMULATOR_CSS_POSITION_SELECTOR": "default",
78
            "SIMULATOR_DISPLAY_CSS_POSITION": "sdk.simulator.positions.INNER",
79
            "SIMULATOR_CSS_PRICE_SELECTOR": "default",
80
            "SIMULATOR_CSS_QUANTITY_SELECTOR": "default",
81
            "SIMULATOR_CSS_PRODUCT_PAGE_STYLES": "",
82
            "SIMULATOR_CSS_CHECKOUT_PAGE_STYLES": "",   
83
            "SIMULATOR_DISPLAY_MAX_AMOUNT": "1500",
84
            "FORM_DISPLAY_TYPE" : "0",
85
            "DISPLAY_MIN_AMOUNT": "0",
86
            "DISPLAY_MAX_AMOUNT": "1500",
87
            "PROMOTION_EXTRA": "Finance this product <span class=pg-no-interest>without interest!</span>",
88
            "SIMULATOR_THOUSAND_SEPARATOR": ".",
89
            "SIMULATOR_DECIMAL_SEPARATOR": ","
90
            }',
91
    );
92
    /**
93
     * @var null $shippingAddress
94
     */
95
    protected $shippingAddress = null;
96
    /**
97
     * @var null $billingAddress
98
     */
99
    protected $billingAddress = null;
100
101
    /**
102
     * @var array $allowedCountries
103
     */
104
    protected $allowedCountries = array();
105
106
    /**
107
     * Pagantis constructor.
108
     *
109
     * Define the module main properties so that prestashop understands what are the module requirements
110
     * and how to manage the module.
111
     *
112
     */
113
    public function __construct()
114
    {
115
        $this->name = 'pagantis';
116
        $this->tab = 'payments_gateways';
117
        $this->version = '8.6.9';
118
        $this->author = 'Pagantis';
119
        $this->currencies = true;
120
        $this->currencies_mode = 'checkbox';
121
        $this->module_key = '2b9bc901b4d834bb7069e7ea6510438f';
122
        $this->ps_versions_compliancy = array('min' => '1.5', 'max' => _PS_VERSION_);
123
        $this->displayName = $this->l('Pagantis');
124
        $this->description = $this->l(
125
            'Instant, easy and effective financial tool for your customers'
126
        );
127
128
        $current_context = Context::getContext();
129
        if (!is_null($current_context->controller) && $current_context->controller->controller_type != 'front') {
130
            $sql_file = dirname(__FILE__).'/sql/install.sql';
131
            $this->loadSQLFile($sql_file);
132
            $this->checkEnvVariables();
133
            $this->migrate();
134
            $this->checkHooks();
135
            $this->checkPromotionCategory();
136
        }
137
138
        parent::__construct();
139
140
        $this->getUserLanguage();
141
    }
142
143
    /**
144
     * Configure the variables for Pagantis payment method.
145
     *
146
     * @return bool
147
     */
148
    public function install()
149
    {
150
        if (!extension_loaded('curl')) {
151
            $this->_errors[] =
152
                $this->l('You have to enable the cURL extension on your server to install this module');
153
            return false;
154
        }
155
        if (!version_compare(phpversion(), '5.3.0', '>=')) {
156
            $this->_errors[] = $this->l('The PHP version bellow 5.3.0 is not supported');
157
            return false;
158
        }
159
160
        $products = explode(',', Pagantis::getExtraConfig('PRODUCTS', null));
161
        foreach ($products as $product) {
162
            $code = Tools::strtolower(Pagantis::getExtraConfig('CODE', $product));
163
            if ($code === 'p4x') {
164
                Configuration::updateValue($code . '_simulator_is_enabled', 1);
165
            }
166
            Configuration::updateValue($code . '_is_enabled', 0);
167
            Configuration::updateValue($code . '_public_key', '');
168
            Configuration::updateValue($code . '_private_key', '');
169
        }
170
171
        $return =  (parent::install()
172
            && $this->registerHook('displayShoppingCart')
173
            && $this->registerHook('paymentOptions')
174
            && $this->registerHook('displayProductButtons')
175
            && $this->registerHook('displayProductPriceBlock')
176
            && $this->registerHook('displayOrderConfirmation')
177
            && $this->registerHook('header')
178
        );
179
180
        if ($return && _PS_VERSION_ < "1.7") {
181
            $this->registerHook('payment');
182
        }
183
184
        return $return;
185
    }
186
187
    /**
188
     * Remove the production private api key and remove the files
189
     *
190
     * @return bool
191
     */
192
    public function uninstall()
193
    {
194
        Configuration::deleteByName('4x_public_key');
195
        Configuration::deleteByName('12x_public_key');
196
        Configuration::deleteByName('4x_public_key');
197
        Configuration::deleteByName('12x_public_key');
198
199
        return parent::uninstall();
200
    }
201
202
    /**
203
     * Migrate the configs of simple 8x module to multiproduct
204
     */
205
    public function migrate()
206
    {
207
    }
208
209
    /**
210
     * Check if new hooks used in new 7x versions are enabled and activate them if needed
211
     *
212
     * @throws PrestaShopDatabaseException
213
     */
214
    public function checkHooks()
215
    {
216
        try {
217
            $sql_content = 'select * from ' . _DB_PREFIX_. 'hook_module where 
218
            id_module = \'' . Module::getModuleIdByName($this->name) . '\' and 
219
            id_shop = \'' . Shop::getContextShopID() . '\' and 
220
            id_hook = \'' . Hook::getIdByName('header') . '\'';
221
            $hook_exists = Db::getInstance()->ExecuteS($sql_content);
222
            if (empty($hook_exists)) {
223
                $sql_insert = 'insert into ' . _DB_PREFIX_.  'hook_module 
224
            (id_module, id_shop, id_hook, position)
225
            values
226
            (\''. Module::getModuleIdByName($this->name) . '\',
227
            \''. Shop::getContextShopID() . '\',
228
            \''. Hook::getIdByName('header') . '\',
229
            150)';
230
                Db::getInstance()->execute($sql_insert);
231
            }
232
233
            $sql_content = 'select * from ' . _DB_PREFIX_. 'hook_module where 
234
            id_module = \'' . Module::getModuleIdByName($this->name) . '\' and 
235
            id_shop = \'' . Shop::getContextShopID() . '\' and 
236
            id_hook = \'' . Hook::getIdByName('displayProductPriceBlock') . '\'';
237
            $hook_exists = Db::getInstance()->ExecuteS($sql_content);
238
            if (empty($hook_exists)) {
239
                $sql_insert = 'insert into ' . _DB_PREFIX_.  'hook_module 
240
            (id_module, id_shop, id_hook, position)
241
            values
242
            (\''. Module::getModuleIdByName($this->name) . '\',
243
            \''. Shop::getContextShopID() . '\',
244
            \''. Hook::getIdByName('displayProductPriceBlock') . '\',
245
            160)';
246
                Db::getInstance()->execute($sql_insert);
247
            }
248
        } catch (\Exception $exception) {
249
            // continue without errors
250
        }
251
    }
252
253
    /**
254
     * @throws PrestaShopDatabaseException
255
     */
256
    public function checkEnvVariables()
257
    {
258
        $sql_content = 'select * from ' . _DB_PREFIX_. 'pagantis_config';
259
        $dbConfigs = Db::getInstance()->executeS($sql_content);
260
261
        // Convert a multimple dimension array for SQL insert statements into a simple key/value
262
        $simpleDbConfigs = array();
263
        foreach ($dbConfigs as $config) {
264
            $simpleDbConfigs[$config['config']] = $config['value'];
265
        }
266
        $newConfigs = array_diff_key($this->defaultConfigs, $simpleDbConfigs);
267
        if (!empty($newConfigs)) {
268
            $data = array();
269
            foreach ($newConfigs as $key => $value) {
270
                $data[] = array(
271
                    'config' => $key,
272
                    'value' => $value,
273
                );
274
            }
275
            Db::getInstance()->insert('pagantis_config', $data);
276
        }
277
    }
278
279
    /**
280
     * @param $sql_file
281
     * @return bool
282
     */
283
    public function loadSQLFile($sql_file)
284
    {
285
        try {
286
            $tableName = _DB_PREFIX_.'pagantis_order';
287
            $sql = "show tables like '"   . $tableName . "'";
288
            $data = Db::getInstance()->ExecuteS($sql);
289
            if (count($data) > 0) {
290
                $sql = "desc "   . $tableName;
291
                $data = Db::getInstance()->ExecuteS($sql);
292
                if (count($data) == 2) {
293
                    $sql = "ALTER TABLE $tableName ADD COLUMN ps_order_id VARCHAR(60) AFTER order_id";
294
                    Db::getInstance()->Execute($sql);
295
                }
296
                if (count($data) == 3) {
297
                    $sql = "ALTER TABLE " . $tableName ." ADD COLUMN  token VARCHAR(32) NOT NULL AFTER order_id";
298
                    Db::getInstance()->Execute($sql);
299
                    $sql = "ALTER TABLE ps_pagantis_order DROP PRIMARY KEY, ADD PRIMARY KEY(id, order_id);";
300
                    Db::getInstance()->Execute($sql);
301
                }
302
303
            $tableName = _DB_PREFIX_.'pagantis_config';
304
            $sql = "show tables like '"   . $tableName . "'";
305
            $data = Db::getInstance()->ExecuteS($sql);
306
            if (count($data) > 0) {
307
                $sql = "desc "   . $tableName;
308
                $data = Db::getInstance()->ExecuteS($sql);
309
                if (count($data) === 3 && $data[2]['Type'] !== 'varchar(5000)') {
310
                    $sql = "ALTER TABLE $tableName MODIFY `value` VARCHAR(5000)";
311
                    Db::getInstance()->Execute($sql);
312
                }
313
                // return because pagantis tables exisit so load the sqlfile is not needed
314
                return true;
315
            }
316
        } catch (\Exception $exception) {
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected T_CATCH on line 316 at column 10
Loading history...
317
            // do nothing
318
        }
319
320
        $sql_content = Tools::file_get_contents($sql_file);
321
        $sql_content = str_replace('PREFIX_', _DB_PREFIX_, $sql_content);
322
        $sql_requests = preg_split("/;\s*[\r\n]+/", $sql_content);
323
324
        $result = true;
325
        foreach ($sql_requests as $request) {
326
            if (!empty($request)) {
327
                $result &= Db::getInstance()->execute(trim($request));
328
            }
329
        }
330
331
        return $result;
332
    }
333
334
    /**
335
     * Check amount of order > minAmount
336
     * Check valid currency
337
     * Check API variables are set
338
     *
339
     * @param string $product
340
     * @return bool
341
     */
342
    public function isPaymentMethodAvailable($product = 'p4x')
343
    {
344
        $configs = json_decode(Pagantis::getExtraConfig($product, null), true);
345
        $cart                      = $this->context->cart;
346
        $currency                  = new Currency($cart->id_currency);
347
        $availableCurrencies       = array('EUR');
348
        $pagantisDisplayMinAmount  = $configs['DISPLAY_MIN_AMOUNT'];
349
        $pagantisDisplayMaxAmount  = $configs['DISPLAY_MAX_AMOUNT'];
350
        $pagantisPublicKey         = Configuration::get(Tools::strtolower($configs['CODE']) . '_public_key');
351
        $pagantisPrivateKey        = Configuration::get(Tools::strtolower($configs['CODE']) . '_private_key');
352
        $this->allowedCountries    = unserialize(Pagantis::getExtraConfig('ALLOWED_COUNTRIES', null));
353
        $this->getUserLanguage();
354
        return (
355
            $cart->getOrderTotal() >= $pagantisDisplayMinAmount &&
356
            ($cart->getOrderTotal() <= $pagantisDisplayMaxAmount || $pagantisDisplayMaxAmount == '0') &&
357
            in_array($currency->iso_code, $availableCurrencies) &&
358
            in_array(Tools::strtolower($this->language), $this->allowedCountries) &&
359
            $pagantisPublicKey &&
360
            $pagantisPrivateKey
361
        );
362
    }
363
364
    /**
365
     * @param Cart $cart
366
     *
367
     * @return array
368
     * @throws Exception
369
     */
370
    private function getButtonTemplateVars(Cart $cart)
371
    {
372
        $currency = new Currency(($cart->id_currency));
373
374
        return array(
375
            'button' => '#payment_button',
376
            'currency_iso' => $currency->iso_code,
377
            'cart_total' => $cart->getOrderTotal(),
378
        );
379
    }
380
381
    /**
382
     * Header hook
383
     */
384
    public function hookHeader()
385
    {
386
387
        $url = 'https://cdn.pagantis.com/js/pg-v2/sdk.js';
388
        if (_PS_VERSION_ >= "1.7") {
389
            $this->context->controller->registerJavascript(
390
                sha1(mt_rand(1, 90000)),
391
                $url,
392
                array('server' => 'remote')
393
            );
394
        } else {
395
            $this->context->controller->addJS($url);
396
        }
397
    }
398
399
    /**
400
     * @return array
401
     * @throws Exception
402
     */
403
    public function hookPaymentOptions()
404
    {
405
        /** @var Cart $cart */
406
        $cart = $this->context->cart;
407
        $this->shippingAddress = new Address($cart->id_address_delivery);
408
        $this->billingAddress = new Address($cart->id_address_invoice);
409
410
        $orderTotal = $cart->getOrderTotal();
411
        $promotedAmount = 0;
412
        $link = $this->context->link;
413
        $items = $cart->getProducts(true);
414
        foreach ($items as $item) {
415
            $itemCategories = ProductCore::getProductCategoriesFull($item['id_product']);
416
            if (in_array(PROMOTIONS_CATEGORY_NAME, $this->arrayColumn($itemCategories, 'name')) !== false) {
417
                $productId = $item['id_product'];
418
                $promotedAmount += Product::getPriceStatic($productId);
419
            }
420
        }
421
422
        $return = array();
423
        $this->context->smarty->assign($this->getButtonTemplateVars($cart));
424
        $products = explode(',', Pagantis::getExtraConfig('PRODUCTS', null));
425
        $templateConfigs = array();
426
        foreach ($products as $product) {
427
            if ($this->isPaymentMethodAvailable($product)) {
428
                $productConfigs = Pagantis::getExtraConfig($product, null);
429
                $productConfigs = json_decode($productConfigs, true);
430
                $publicKey = Configuration::get(Tools::strtolower($productConfigs['CODE']) . '_public_key');
431
                $simulatorIsEnabled = Configuration::get(Tools::strtolower($productConfigs['CODE']) . '_simulator_is_enabled');
432
                $isEnabled = Configuration::get(Tools::strtolower($productConfigs['CODE']) . '_is_enabled');
433
434
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_TITLE'] = $this->l($productConfigs['TITLE']);
435
                unset($productConfigs['TITLE']);
436
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_AMOUNT'] = $orderTotal;
437
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_PROMOTED_AMOUNT'] = $promotedAmount;
438
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_LOCALE'] = $this->language;
439
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_COUNTRY'] = $this->language;
440
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_PUBLIC_KEY'] = $publicKey;
441
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_SIMULATOR_IS_ENABLED'] = $simulatorIsEnabled;
442
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_IS_ENABLED'] = $isEnabled;
443
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_LOGO'] = 'https://cdn.digitalorigin.com/assets/master/logos/pg-favicon.png';
444
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_PAYMENT_URL'] = $link->getModuleLink('pagantis', 'payment') . '&product=' . $productConfigs['CODE'];
445
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_PS_VERSION'] = str_replace('.', '-', Tools::substr(_PS_VERSION_, 0, 3));
446
447
                foreach ($productConfigs as $productConfigKey => $productConfigValue) {
448
                    $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . "_" . $productConfigKey] = $productConfigValue;
449
                }
450
                $this->context->smarty->assign($templateConfigs);
451
452
                $paymentOption = new PrestaShop\PrestaShop\Core\Payment\PaymentOption();
453
                $uri = $link->getModuleLink('pagantis', 'payment');
454
                if (strpos($uri, '?') !== false) {
455
                    $uri .= '&product=' . $productConfigs['CODE'];
456
                } else {
457
                    $uri .= '?product=' . $productConfigs['CODE'];
458
                }
459
                $paymentOption
460
                    ->setCallToActionText($templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_TITLE'])
461
                    ->setAction($uri)
462
                    ->setLogo($templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_LOGO'])
463
                    ->setModuleName(__CLASS__)
464
                    ->setAdditionalInformation(
465
                        $this->fetch('module:pagantis/views/templates/hook/checkout-' . Tools::strtolower($productConfigs['CODE']) . '.tpl')
466
                    )
467
                ;
468
                $return[] = $paymentOption;
469
            }
470
        }
471
        if (count($return) === 0) {
472
            return false;
473
        }
474
        return $return;
475
    }
476
477
    /**
478
     * Get the form for editing the BackOffice options of the module
479
     *
480
     * @return array
481
            */
482
    private function getConfigForm()
483
    {
484
        $products = explode(',', Pagantis::getExtraConfig('PRODUCTS', null));
485
        $inputs = array();
486
        foreach ($products as $product) {
487
            $code = Tools::strtolower(Pagantis::getExtraConfig('CODE', $product));
488
            $inputs[] = array(
489
                'name' => $code .'_is_enabled',
490
                'type' =>  (version_compare(_PS_VERSION_, '1.6')<0) ?'radio' :'switch',
491
                'label' => $this->l('Module is enabled ' . $code),
492
                'prefix' => '<i class="icon icon-key"></i>',
493
                'class' => 't',
494
                'required' => true,
495
                'values'=> array(
496
                    array(
497
                        'id' => $code .'_is_enabled_true',
498
                        'value' => 1,
499
                        'label' => $this->l('Yes', get_class($this), null, false),
500
                    ),
501
                    array(
502
                        'id' => $code . '_is_enabled_false',
503
                        'value' => 0,
504
                        'label' => $this->l('No', get_class($this), null, false),
505
                    ),
506
                )
507
            );
508
            $inputs[] = array(
509
                'name' => $code . '_public_key',
510
                'suffix' => $this->l('ex: pk_fd53cd467ba49022e4gf215e'),
511
                'type' => 'text',
512
                'size' => 60,
513
                'label' => $this->l('Public Key ' . $code),
514
                'prefix' => '<i class="icon icon-key"></i>',
515
                'col' => 6,
516
                'required' => true,
517
            );
518
            $inputs[] = array(
519
                'name' => $code . '_private_key',
520
                'suffix' => $this->l('ex: 21e5723a97459f6a'),
521
                'type' => 'text',
522
                'size' => 60,
523
                'label' => $this->l('Private Key ' . $code),
524
                'prefix' => '<i class="icon icon-key"></i>',
525
                'col' => 6,
526
                'required' => true,
527
            );
528
            if ($code !== "p4x") {
529
                $inputs[] = array(
530
                    'name' => $code . '_simulator_is_enabled',
531
                    'type' => (version_compare(_PS_VERSION_, '1.6')<0) ?'radio' :'switch',
532
                    'label' => $this->l('Simulator is enabled ' . $code),
533
                    'prefix' => '<i class="icon icon-key"></i>',
534
                    'class' => 't',
535
                    'required' => true,
536
                    'values'=> array(
537
                        array(
538
                            'id' => $code . '_simulator_is_enabled_on',
539
                            'value' => 1,
540
                            'label' => $this->l('Yes'),
541
                        ),
542
                        array(
543
                            'id' => $code . '_simulator_is_enabled_off',
544
                            'value' => 0,
545
                            'label' => $this->l('No'),
546
                        ),
547
                    )
548
                );
549
            }
550
        }
551
        $return = array(
552
            'form' => array(
553
                'legend' => array(
554
                    'title' => $this->l('Basic Settings'),
555
                    'icon' => 'icon-cogs',
556
                ),
557
                'input' => $inputs,
558
                'submit' => array(
559
                    'title' => $this->l('Save'),
560
                )
561
            )
562
        );
563
        return $return;
564
    }
565
566
    /**
567
     * Form configuration function
568
     *
569
     * @param array $settings
570
     *
571
     * @return string
572
     */
573
    private function renderForm(array $settings)
574
    {
575
        $helper = new HelperForm();
576
        $helper->show_toolbar = false;
577
        $helper->table = $this->table;
578
        $helper->module = $this;
579
        $helper->default_form_language = $this->context->language->id;
580
        $helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG', 0);
581
        $helper->identifier = $this->identifier;
582
        $helper->submit_action = 'submit'.$this->name;
583
        $helper->currentIndex = AdminController::$currentIndex.'&configure='.$this->name;
584
        $helper->token = Tools::getAdminTokenLite('AdminModules');
585
        $helper->tpl_vars = array(
586
            'fields_value' => $settings,
587
            'languages' => $this->context->controller->getLanguages(),
588
            'id_language' => $this->context->language->id,
589
        );
590
591
        $helper->fields_value['url_ok'] = Configuration::get('url_ok');
592
593
        return $helper->generateForm(array($this->getConfigForm()));
594
    }
595
596
    /**
597
     * Function to update the variables of Pagantis Module in the backoffice of prestashop
598
     *
599
     * @return string
600
     * @throws SmartyException
601
     */
602
    public function getContent()
603
    {
604
        $error = '';
605
        $message = '';
606
        $settings = array();
607
        $settingsKeys = array();
608
        $products = explode(',', Pagantis::getExtraConfig('PRODUCTS', null));
609
        foreach ($products as $product) {
610
            $code = Tools::strtolower(Pagantis::getExtraConfig('CODE', $product));
611
            $settings[$code . '_public_key'] = Configuration::get($code . '_public_key');
612
            $settings[$code . '_private_key'] = Configuration::get($code . '_private_key');
613
            $settings[$code . '_is_enabled'] = Configuration::get($code . '_is_enabled');
614
            if ($code !== 'p4x') {
615
                $settings[$code . '_simulator_is_enabled'] = Configuration::get($code . '_simulator_is_enabled');
616
            }
617
            $settingsKeys[] = $code . '_is_enabled';
618
            $settingsKeys[] = $code . '_public_key';
619
            $settingsKeys[] = $code . '_private_key';
620
            if ($code !== 'p4x') {
621
                $settingsKeys[] = $code . '_simulator_is_enabled';
622
            }
623
        }
624
625
        //Different Behavior depending on 1.6 or earlier
626
        if (Tools::isSubmit('submit'.$this->name)) {
627
            foreach ($settingsKeys as $key) {
628
                $value = Tools::getValue($key);
629
                Configuration::updateValue($key, $value);
630
                $settings[$key] = $value;
631
            }
632
            $message = $this->displayConfirmation($this->l('All changes have been saved'));
633
        } else {
634
            foreach ($settingsKeys as $key) {
635
                    $settings[$key] = Configuration::get($key);
636
            }
637
        }
638
        if ($error) {
639
            $message = $this->displayError($error);
640
        }
641
642
        $logo = 'https://cdn.digitalorigin.com/assets/master/logos/pg.png';
643
        $tpl = $this->local_path.'views/templates/admin/config-info.tpl';
644
        $this->context->smarty->assign(array(
645
            'logo' => $logo,
646
            'form' => $this->renderForm($settings),
647
            'message' => $message,
648
            'version' => 'v'.$this->version,
649
        ));
650
651
        return $this->context->smarty->fetch($tpl);
652
    }
653
654
    /**
655
     * Hook to show payment method, this only applies on prestashop <= 1.6
656
     *
657
     * @param $params
658
     * @return bool | string
659
     * @throws Exception
660
     */
661
    public function hookPayment($params)
662
    {
663
        /** @var Cart $cart */
664
        $cart = $this->context->cart;
665
        $this->shippingAddress = new Address($cart->id_address_delivery);
666
        $this->billingAddress = new Address($cart->id_address_invoice);
667
668
        $orderTotal = $cart->getOrderTotal();
669
        $promotedAmount = 0;
670
        $link = $this->context->link;
671
        $items = $cart->getProducts(true);
672
        foreach ($items as $item) {
673
            $itemCategories = ProductCore::getProductCategoriesFull($item['id_product']);
674
            if (in_array(PROMOTIONS_CATEGORY_NAME, $this->arrayColumn($itemCategories, 'name')) !== false) {
675
                $productId = $item['id_product'];
676
                $promotedAmount += Product::getPriceStatic($productId);
677
            }
678
        }
679
680
        $supercheckout_enabled = Module::isEnabled('supercheckout');
681
        $onepagecheckoutps_enabled = Module::isEnabled('onepagecheckoutps');
682
        $onepagecheckout_enabled = Module::isEnabled('onepagecheckout');
683
684
        $return = '';
685
        $this->context->smarty->assign($this->getButtonTemplateVars($cart));
686
        $products = explode(',', Pagantis::getExtraConfig('PRODUCTS', null));
687
        $templateConfigs = array();
688
        foreach ($products as $product) {
689
            if ($this->isPaymentMethodAvailable($product)) {
690
                $productConfigs = Pagantis::getExtraConfig($product, null);
691
                $productConfigs = json_decode($productConfigs, true);
692
                $publicKey = Configuration::get(Tools::strtolower($productConfigs['CODE']) . '_public_key');
693
                $simulatorIsEnabled = Configuration::get(Tools::strtolower($productConfigs['CODE']) . '_simulator_is_enabled');
694
                $isEnabled = Configuration::get(Tools::strtolower($productConfigs['CODE']) . '_is_enabled');
695
696
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_TITLE'] = $this->l($productConfigs['TITLE']);
697
                unset($productConfigs['TITLE']);
698
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_AMOUNT'] = $orderTotal;
699
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_PROMOTED_AMOUNT'] = $promotedAmount;
700
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_LOCALE'] = $this->language;
701
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_COUNTRY'] = $this->language;
702
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_PUBLIC_KEY'] = $publicKey;
703
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_SIMULATOR_IS_ENABLED'] = $simulatorIsEnabled;
704
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_IS_ENABLED'] = $isEnabled;
705
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_LOGO'] = 'https://cdn.digitalorigin.com/assets/master/logos/pg-favicon.png';
706
                $uri = $link->getModuleLink('pagantis', 'payment');
707
                if (strpos($uri, '?') !== false) {
708
                    $uri .= '&product=' . $productConfigs['CODE'];
709
                } else {
710
                    $uri .= '?product=' . $productConfigs['CODE'];
711
                }
712
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_PAYMENT_URL'] = $uri;
713
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_PS_VERSION'] = str_replace('.', '-', Tools::substr(_PS_VERSION_, 0, 3));
714
715
                foreach ($productConfigs as $productConfigKey => $productConfigValue) {
716
                    $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . "_" . $productConfigKey] = $productConfigValue;
717
                }
718
                $this->context->smarty->assign($templateConfigs);
719
                if ($supercheckout_enabled || $onepagecheckout_enabled || $onepagecheckoutps_enabled) {
720
                    $this->checkLogoExists();
721
                    $return .= $this->display(
722
                        __FILE__,
723
                        'views/templates/hook/onepagecheckout-' . Tools::strtolower($productConfigs['CODE']) . '.tpl'
724
                    );
725
                } elseif (_PS_VERSION_ < 1.7) {
726
                    $return .= $this->display(
727
                        __FILE__,
728
                        'views/templates/hook/checkout-' . Tools::strtolower($productConfigs['CODE']) . '.tpl'
729
                    );
730
                }
731
            }
732
        }
733
734
        return $return;
735
    }
736
737
    /**
738
     * @param string $hookName
739
     * @return bool|string
740
     */
741
    public function productPageSimulatorDisplay($hookName = '')
742
    {
743
        $productId = Tools::getValue('id_product');
744
        if (!$productId) {
745
            return false;
746
        }
747
        //Resolves bug of reference passtrow
748
        $amount = Product::getPriceStatic($productId);
749
        $allowedCountries = unserialize(Pagantis::getExtraConfig('ALLOWED_COUNTRIES', null));
750
751
        $itemCategoriesNames = $this->arrayColumn(Product::getProductCategoriesFull($productId), 'name');
752
        $isPromotedProduct = in_array(PROMOTIONS_CATEGORY_NAME, $itemCategoriesNames);
753
754
        $return = '';
755
        $products = explode(',', Pagantis::getExtraConfig('PRODUCTS', null));
756
        $templateConfigs = array();
757
        foreach ($products as $product) {
758
            $productConfigs = Pagantis::getExtraConfig($product, null);
759
            $productConfigs = json_decode($productConfigs, true);
760
761
            $publicKey = Configuration::get(Tools::strtolower($productConfigs['CODE']) . '_public_key');
762
            $simulatorIsEnabled = Configuration::get(Tools::strtolower($productConfigs['CODE']) . '_simulator_is_enabled');
763
            if (Tools::strtolower($productConfigs['CODE']) === 'p4x') {
764
                $simulatorIsEnabled = true;
765
            }
766
            $isEnabled = Configuration::get(Tools::strtolower($productConfigs['CODE']) . '_is_enabled');
767
            $availableSimulators = array(
768
                'hookDisplayProductButtons' => array(
769
                    'sdk.simulator.types.SIMPLE',
770
                    'sdk.simulator.types.SELECTABLE',
771
                    'sdk.simulator.types.MARKETING',
772
                    'sdk.simulator.types.TEXT'
773
                ),
774
                'hookDisplayProductPriceBlock' => array(
775
                    'sdk.simulator.types.PRODUCT_PAGE',
776
                    'sdk.simulator.types.SELECTABLE_TEXT_CUSTOM',
777
                    'p4x',
778
                )
779
            );
780
            if ($isEnabled &&
781
                $simulatorIsEnabled &&
782
                $amount > 0 &&
783
                $amount > $productConfigs['DISPLAY_MIN_AMOUNT'] &&
784
                ($amount < $productConfigs['DISPLAY_MAX_AMOUNT'] || $productConfigs['DISPLAY_MAX_AMOUNT'] === '0') &&
785
                ($amount < $productConfigs['SIMULATOR_DISPLAY_MAX_AMOUNT'] || $productConfigs['SIMULATOR_DISPLAY_MAX_AMOUNT'] === '0') &&
786
                in_array(Tools::strtolower($this->language), $allowedCountries) &&
787
                (in_array($productConfigs['SIMULATOR_DISPLAY_TYPE'], $availableSimulators[$hookName]) || _PS_VERSION_ < 1.6)
788
            ) {
789
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_TITLE'] = $this->l($productConfigs['TITLE']);
790
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_SIMULATOR_TITLE'] = $this->l($productConfigs['SIMULATOR_TITLE']);
791
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_SIMULATOR_SUBTITLE'] = $this->l($productConfigs['SIMULATOR_SUBTITLE']);
792
                unset($productConfigs['TITLE']);
793
                unset($productConfigs['SIMULATOR_TITLE']);
794
                unset($productConfigs['SIMULATOR_SUBTITLE']);
795
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_AMOUNT'] = $amount;
796
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_AMOUNT4X'] = number_format(($amount / 4), 2, '.', '');
797
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_IS_PROMOTED_PRODUCT'] = $isPromotedProduct;
798
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_LOCALE'] = $this->language;
799
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_COUNTRY'] = $this->language;
800
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_PUBLIC_KEY'] = $publicKey;
801
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_SIMULATOR_IS_ENABLED'] = $simulatorIsEnabled;
802
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_IS_ENABLED'] = $isEnabled;
803
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_LOGO'] = 'https://cdn.digitalorigin.com/assets/master/logos/pg-favicon.png';
804
                $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . '_PS_VERSION'] = str_replace('.', '-', Tools::substr(_PS_VERSION_, 0, 3));
805
                foreach ($productConfigs as $productConfigKey => $productConfigValue) {
806
                    $templateConfigs[Tools::strtoupper(Tools::strtolower($productConfigs['CODE'])) . "_" . $productConfigKey] = $productConfigValue;
807
                }
808
809
                $this->context->smarty->assign($templateConfigs);
810
                $return .= $this->display(
811
                    __FILE__,
812
                    'views/templates/hook/product-simulator-' . Tools::strtolower($productConfigs['CODE']) . '.tpl'
813
                );
814
            }
815
        }
816
817
        return $return;
818
    }
819
820
    /**
821
     * @return string
822
     * @throws PrestaShopDatabaseException
823
     * @throws PrestaShopException
824
     */
825
    public function hookDisplayProductButtons()
826
    {
827
        return $this->productPageSimulatorDisplay("hookDisplayProductButtons");
828
    }
829
830
    /**
831
     * @param $params
832
     * @return string
833
     * @throws PrestaShopDatabaseException
834
     * @throws PrestaShopException
835
     */
836
    public function hookDisplayProductPriceBlock($params)
837
    {
838
        // $params['type'] = weight | price | after_price
839
        if (isset($params['type']) && $params['type'] === 'price' &&
840
            isset($params['smarty']) && isset($params['smarty']->template_resource) &&
841
            (strpos($params['smarty']->template_resource, 'product.tpl') !== false  ||
842
            strpos($params['smarty']->template_resource, 'product-prices.tpl') !== false)
843
        ) {
844
            return $this->productPageSimulatorDisplay("hookDisplayProductPriceBlock");
845
        }
846
        return '';
847
    }
848
849
    /**
850
     * @param array $params
851
     *
852
     * @return string
853
     */
854
    public function hookDisplayOrderConfirmation($params)
855
    {
856
        $paymentMethod = (_PS_VERSION_ < 1.7) ? ($params["objOrder"]->payment) : ($params["order"]->payment);
857
858
        if ($paymentMethod == $this->displayName) {
859
            return $this->display(__FILE__, 'views/templates/hook/payment-return.tpl');
860
        }
861
862
        return null;
863
    }
864
865
    /**
866
     * checkPromotionCategory
867
     */
868
    public function checkPromotionCategory()
869
    {
870
        $categories = $this->arrayColumn(Category::getCategories(null, false, false), 'name');
871
        if (!in_array(PROMOTIONS_CATEGORY_NAME, $categories)) {
872
            /** @var CategoryCore $category */
873
            $category = new Category();
874
            $categoryArray = array((int)Configuration::get('PS_LANG_DEFAULT')=> PROMOTIONS_CATEGORY );
875
            $category->is_root_category = false;
876
            $category->link_rewrite = $categoryArray;
877
            $category->meta_description = $categoryArray;
878
            $category->meta_keywords = $categoryArray;
879
            $category->meta_title = $categoryArray;
880
            $category->name = array((int)Configuration::get('PS_LANG_DEFAULT')=> PROMOTIONS_CATEGORY_NAME);
881
            $category->id_parent = Configuration::get('PS_HOME_CATEGORY');
882
            $category->active=0;
883
            $description = 'Pagantis: Products with this category have free financing assumed by the merchant. ' .
884
                'Use it to promote your products or brands.';
885
            $category->description = $this->l($description);
886
            $category->save();
887
        }
888
    }
889
890
    /**
891
     * @param null   $config
892
     * @param        $product
893
     * @param string $default
894
     * @return string
895
     */
896
    public static function getExtraConfig($config = null, $product = "P4X", $default = '')
897
    {
898
        if (is_null($config)) {
899
            return '';
900
        }
901
902
        if (is_null($product)) {
903
            $sql = 'SELECT value FROM '._DB_PREFIX_.'pagantis_config where config = \'' . pSQL($config) . '\' limit 1';
904
            if ($results = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS($sql)) {
905
                if (is_array($results) && count($results) === 1 && isset($results[0]['value'])) {
906
                    return $results[0]['value'];
907
                }
908
            }
909
        }
910
911
        $sql = 'SELECT value FROM '._DB_PREFIX_.'pagantis_config where config = \'' . pSQL($product) . '\' limit 1';
912
        if ($results = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS($sql)) {
913
            if (is_array($results) && count($results) === 1 && isset($results[0]['value'])) {
914
                $configs = json_decode($results[0]['value'], true);
915
                $value = '';
916
                if (isset($configs[$config])) {
917
                    $value = $configs[$config];
918
                }
919
                return $value;
920
            }
921
        }
922
923
        return $default;
924
    }
925
926
    /**
927
     * Check logo exists in OPC module
928
     */
929
    public function checkLogoExists()
930
    {
931
        $logoPg = _PS_MODULE_DIR_ . '/onepagecheckoutps/views/img/payments/pagantis.png';
932
        if (!file_exists($logoPg) && is_dir(_PS_MODULE_DIR_ . '/onepagecheckoutps/views/img/payments')) {
933
            copy(
934
                _PS_PAGANTIS_DIR . '/logo.png',
935
                $logoPg
936
            );
937
        }
938
    }
939
940
    /**
941
     * Get user language
942
     */
943
    private function getUserLanguage()
944
    {
945
        $lang = Language::getLanguage($this->context->language->id);
946
        $langArray = explode("-", $lang['language_code']);
947
        if (count($langArray) != 2 && isset($lang['locale'])) {
948
            $langArray = explode("-", $lang['locale']);
949
        }
950
        $this->language = Tools::strtoupper($langArray[count($langArray)-1]);
951
        // Prevent null language detection
952
        if (in_array(Tools::strtolower($this->language), $this->allowedCountries)) {
953
            return;
954
        }
955
        if ($this->shippingAddress) {
956
            $this->language = Country::getIsoById($this->shippingAddress->id_country);
957
            if (in_array(Tools::strtolower($this->language), $this->allowedCountries)) {
958
                return;
959
            }
960
        }
961
        if ($this->billingAddress) {
962
            $this->language = Country::getIsoById($this->billingAddress->id_country);
963
            if (in_array(Tools::strtolower($this->language), $this->allowedCountries)) {
964
                return;
965
            }
966
        }
967
        return $this->language;
968
    }
969
970
    /**
971
     * @param array $input
972
     * @param       $columnKey
973
     * @param null  $indexKey
974
     *
975
     * @return array|bool
976
     */
977
    private function arrayColumn(array $input, $columnKey, $indexKey = null)
978
    {
979
        $array = array();
980
        foreach ($input as $value) {
981
            if (!array_key_exists($columnKey, $value)) {
982
                trigger_error("Key \"$columnKey\" does not exist in array");
983
                return false;
984
            }
985
            if (is_null($indexKey)) {
986
                $array[] = $value[$columnKey];
987
            } else {
988
                if (!array_key_exists($indexKey, $value)) {
989
                    trigger_error("Key \"$indexKey\" does not exist in array");
990
                    return false;
991
                }
992
                if (!is_scalar($value[$indexKey])) {
993
                    trigger_error("Key \"$indexKey\" does not contain scalar value");
994
                    return false;
995
                }
996
                $array[$value[$indexKey]] = $value[$columnKey];
997
            }
998
        }
999
        return $array;
1000
    }
1001
}
1002