Completed
Push — master ( 959b11...15c9ac )
by Marcus
02:05
created

Updatecart::preparePage()   D

Complexity

Conditions 25
Paths 123

Size

Total Lines 122
Code Lines 79

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 122
rs 4.3198
cc 25
eloc 79
nc 123
nop 0

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
/*
4
    HCSF - A multilingual CMS and Shopsystem
5
    Copyright (C) 2014  Marcus Haase - [email protected]
6
7
    This program is free software: you can redistribute it and/or modify
8
    it under the terms of the GNU General Public License as published by
9
    the Free Software Foundation, either version 3 of the License, or
10
    (at your option) any later version.
11
12
    This program is distributed in the hope that it will be useful,
13
    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
    GNU General Public License for more details.
16
17
    You should have received a copy of the GNU General Public License
18
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
 */
20
21
namespace HaaseIT\HCSF\Controller\Shop;
22
23
use HaaseIT\HCSF\HelperConfig;
24
25
/**
26
 * Class Updatecart
27
 * @package HaaseIT\HCSF\Controller\Shop
28
 */
29
class Updatecart extends Base
30
{
31
    /**
32
     *
33
     */
34
    public function preparePage()
0 ignored issues
show
Coding Style introduced by
preparePage uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
35
    {
36
        $this->P = new \HaaseIT\HCSF\CorePage($this->serviceManager);
37
        $this->P->cb_pagetype = 'content';
38
39
        if (
40
            (
41
                HelperConfig::$shop['show_pricesonlytologgedin']
42
                && !\HaaseIT\HCSF\Customer\Helper::getUserData()
43
            )
44
            || filter_input(INPUT_SERVER, 'HTTP_REFERER') === null
45
        ) {
46
            $this->P->oPayload->cl_html = $this->serviceManager->get('textcats')->T('denied_default');
47
        } else {
48
            $iAmount = filter_input(INPUT_POST, 'amount', FILTER_SANITIZE_NUMBER_INT);
49
            $postitemno = filter_input(INPUT_POST, 'itemno', FILTER_SANITIZE_SPECIAL_CHARS);
50
51
            if (empty($postitemno) || !is_numeric($iAmount)) {
52
                $this->replyToCartUpdate('noitemnooramount');
53
            } else {
54
                $iAmount = floor($iAmount);
55
56
                // Check if this item exists
57
                $aData = $this->serviceManager->get('oItem')->sortItems('', $postitemno);
58
                if (!isset($aData)) {
59
                    $this->replyToCartUpdate('itemnotfound');
60
                } else {
61
                    // are there additional items to this item, if so, check if they are valid, too.
62
                    $postadditionalitems = filter_input(INPUT_POST, 'additionalitems', FILTER_SANITIZE_SPECIAL_CHARS);
63
                    if (!empty($postadditionalitems)) {
64
65
                        if (strpos($postadditionalitems, '~') !== false) {
66
                            $postadditionalitems = explode('~', $postadditionalitems);
67
                        } else {
68
                            $postadditionalitems = [$postadditionalitems];
69
                        }
70
71
                        $additionaldata = $this->serviceManager->get('oItem')->sortItems('', $postadditionalitems);
72
73
                        if (count($postadditionalitems) != count($additionaldata['item'])) {
74
                            $this->replyToCartUpdate('itemnotfound');
75
                        }
76
                    }
77
78
                    // build the key for this item for the shoppingcart
79
                    $sItemno = $aData['item'][$postitemno]['itm_no'];
80
                    $sCartKey = $sItemno;
81
82
                    if (isset(HelperConfig::$shop['custom_order_fields'])) {
83
                        foreach (HelperConfig::$shop['custom_order_fields'] as $sValue) {
84
                            if (isset($aData['item'][$sItemno]['itm_data'][$sValue])) {
85
                                $aOptions = [];
86
                                $TMP = explode('|', $aData['item'][$sItemno]['itm_data'][$sValue]);
87
                                foreach ($TMP as $sTMPValue) {
88
                                    if (!empty($sTMPValue)) {
89
                                        $aOptions[] = $sTMPValue;
90
                                    }
91
                                }
92
                                unset($sTMP);
93
94
                                $currentpost = filter_input(INPUT_POST, $sValue);
95
                                if ($currentpost !== null && in_array($currentpost, $aOptions)) {
96
                                    $sCartKey .= '|'.$sValue.':'.$currentpost;
97
                                } else {
98
                                    $this->replyToCartUpdate('requiredfieldmissing');
99
                                }
100
                            }
101
                        }
102
                    }
103
                    // if this Items is not in cart and amount is 0, no need to do anything, return to referer
104
                    if ($iAmount == 0 && !isset($_SESSION['cart'][$sCartKey])) {
105
                        $this->replyToCartUpdate('noactiontaken');
106
                    }
107
                    $aItem = [
108
                        'amount' => $iAmount,
109
                        'price' => $this->serviceManager->get('oItem')->calcPrice($aData['item'][$sItemno]),
110
                        'rg' => $aData['item'][$sItemno]['itm_rg'],
111
                        'vat' => $aData['item'][$sItemno]['itm_vatid'],
112
                        'name' => $aData['item'][$sItemno]['itm_name'],
113
                        'img' => $aData['item'][$sItemno]['itm_img'],
114
                    ];
115
116
                    if (filter_input(INPUT_POST, 'action') === 'add') {
117
                        $this->addItemToCart($sCartKey, $aItem);
118
119
                        if (!empty($postadditionalitems)) {
120
                            foreach ($postadditionalitems as $additionalitem) {
121
                                $this->addItemToCart(
122
                                    $additionalitem,
123
                                    [
124
                                        'amount' => $iAmount,
125
                                        'price' => $this->serviceManager->get('oItem')->calcPrice($additionaldata['item'][$additionalitem]),
0 ignored issues
show
Bug introduced by
The variable $additionaldata 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...
126
                                        'rg' => $additionaldata['item'][$additionalitem]['itm_rg'],
127
                                        'vat' => $additionaldata['item'][$additionalitem]['itm_vatid'],
128
                                        'name' => $additionaldata['item'][$additionalitem]['itm_name'],
129
                                        'img' => $additionaldata['item'][$additionalitem]['itm_img'],
130
                                    ]
131
                                );
132
                            }
133
                        }
134
                    } else {
135
                        if (isset($_SESSION['cart'][$sCartKey])) { // if this item is already in cart, update amount
136
                            if ($iAmount == 0) { // new amount == 0 -> remove from cart
137
                                unset($_SESSION['cart'][$sCartKey]);
138
                                if (count($_SESSION['cart']) == 0) { // once the last cart item is unset, we no longer need cartpricesums
139
                                    unset($_SESSION['cartpricesums']);
140
                                }
141
                                $this->replyToCartUpdate('removed', ['cartkey' => $sCartKey]);
142
                            } else { // update amount
143
                                $_SESSION['cart'][$sCartKey]['amount'] = $iAmount;
144
                                $this->replyToCartUpdate('updated', ['cartkey' => $sCartKey, 'amount' => $iAmount]);
145
                            }
146
                        } else { // if this item is not in the cart yet, add it
147
                            $_SESSION['cart'][$sCartKey] = $aItem;
148
                        }
149
                    }
150
                    $this->replyToCartUpdate('added', ['cartkey' => $sCartKey, 'amount' => $iAmount]);
151
                }
152
            }
153
            \HaaseIT\HCSF\Helper::terminateScript();
154
        }
155
    }
156
157
    /**
158
     * @param string $sReply
159
     * @param array $aMore
160
     */
161
    private function replyToCartUpdate($sReply, $aMore = []) {
0 ignored issues
show
Coding Style introduced by
replyToCartUpdate uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
162
        if (filter_input(INPUT_GET, 'ajax') !== null) {
163
            $aAR = [
164
                'cart' => $_SESSION['cart'],
165
                'reply' => $sReply,
166
                'cartsums' => \HaaseIT\HCSF\Shop\Helper::calculateCartItems($_SESSION['cart']),
167
                'currency' => HelperConfig::$shop['waehrungssymbol'],
168
                'numberformat_decimals' => HelperConfig::$core['numberformat_decimals'],
169
                'numberformat_decimal_point' => HelperConfig::$core['numberformat_decimal_point'],
170
                'numberformat_thousands_seperator' => HelperConfig::$core['numberformat_thousands_seperator'],
171
            ];
172
            if (count($aMore)) {
173
                $aAR = array_merge($aAR, $aMore);
174
            }
175
            echo $this->serviceManager->get('twig')->render('shop/update-cart.twig', $aAR);
176
        } else {
177
            $aMSG['msg'] =  $sReply;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$aMSG was never initialized. Although not strictly required by PHP, it is generally a good practice to add $aMSG = 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...
178
            if (count($aMore)) {
179
                $aMSG = array_merge($aMSG, $aMore);
180
            }
181
            header('Location: '.\HaaseIT\Toolbox\Tools::makeLinkHRefWithAddedGetVars(filter_input(INPUT_SERVER, 'HTTP_REFERER', FILTER_SANITIZE_URL), $aMSG, true, false));
182
        }
183
        \HaaseIT\HCSF\Helper::terminateScript();
184
    }
185
186
    protected function addItemToCart($cartkey, $item)
0 ignored issues
show
Coding Style introduced by
addItemToCart uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
187
    {
188
        if (isset($_SESSION['cart'][$cartkey])) { // if this item is already in cart, add to amount
189
            $_SESSION['cart'][$cartkey]['amount'] += $item['amount'];
190
        } else {
191
            $_SESSION['cart'][$cartkey] = $item;
192
        }
193
194
        return true;
195
    }
196
}
197