Completed
Push — master ( 934151...9c9d88 )
by Marcus
02:32
created

Itemadmin   B

Complexity

Total Complexity 51

Size/Duplication

Total Lines 430
Duplicated Lines 2.79 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 51
c 1
b 0
f 0
lcom 1
cbo 9
dl 12
loc 430
rs 8.3206

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
D preparePage() 0 93 17
B admin_prepareItemlistsearchform() 12 28 5
C admin_getItemlist() 0 46 8
A admin_prepareItemlist() 0 22 2
B admin_getItem() 0 36 4
B admin_prepareItem() 0 49 6
B admin_updateItem() 0 58 6
A admin_getItemgroups() 0 21 2

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

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\Admin\Shop;
22
23
24
use HaaseIT\HCSF\HardcodedText;
25
use HaaseIT\HCSF\HelperConfig;
26
use HaaseIT\Toolbox\Tools;
27
use Zend\Diactoros\ServerRequest;
28
use Zend\ServiceManager\ServiceManager;
29
30
/**
31
 * Class Itemadmin
32
 * @package HaaseIT\HCSF\Controller\Admin\Shop
33
 */
34
class Itemadmin extends Base
35
{
36
    /**
37
     * @var \PDO
38
     */
39
    protected $db;
40
41
    /**
42
     * @var \Doctrine\DBAL\Connection
43
     */
44
    protected $dbal;
45
46
    /**
47
     * @var array
48
     */
49
    protected $get;
50
51
    /**
52
     * @var array
53
     */
54
    protected $post;
55
56
    /**
57
     * @var ServerRequest;
58
     */
59
    protected $request;
60
61
    /**
62
     * Itemadmin constructor.
63
     * @param ServiceManager $serviceManager
64
     */
65
    public function __construct(ServiceManager $serviceManager)
66
    {
67
        parent::__construct($serviceManager);
68
        $this->db = $serviceManager->get('db');
69
        $this->dbal = $serviceManager->get('dbal');
70
        $this->request = $serviceManager->get('request');
71
        $this->get = $this->request->getQueryParams();
72
        $this->post = $this->request->getParsedBody();
73
    }
74
75
    /**
76
     *
77
     */
78
    public function preparePage()
79
    {
80
        $this->P = new \HaaseIT\HCSF\CorePage($this->serviceManager);
81
        $this->P->cb_pagetype = 'content';
82
        $this->P->cb_subnav = 'admin';
83
84
        $this->P->cb_customcontenttemplate = 'shop/itemadmin';
85
86
        if (isset($this->get['action']) && $this->get['action'] === 'insert_lang') {
87
            $aItemdata = $this->admin_getItem();
88
89
            if (isset($aItemdata['base']) && !isset($aItemdata['text'])) {
90
                $querybuilder = $this->dbal->createQueryBuilder();
91
                $querybuilder
92
                    ->insert('item_lang')
93
                    ->setValue('itml_pid', '?')
94
                    ->setValue('itml_lang', '?')
95
                    ->setParameter(0, $aItemdata['base']['itm_id'])
96
                    ->setParameter(1, HelperConfig::$lang)
97
                ;
98
                $querybuilder->execute();
99
100
                \HaaseIT\HCSF\Helper::redirectToPage('/_admin/itemadmin.html?itemno='.$this->get['itemno'].'&action=showitem');
101
            }
102
        }
103
        $this->P->cb_customdata['searchform'] = $this->admin_prepareItemlistsearchform();
104
105
        if (isset($this->get['action'])) {
106
            if ($this->get['action'] === 'search') {
107
                $this->P->cb_customdata['searchresult'] = true;
108
                if ($aItemlist = $this->admin_getItemlist()) {
109
                    if (count($aItemlist['data']) == 1) {
110
                        $aItemdata = $this->admin_getItem($aItemlist['data'][0]['itm_no']);
111
                        $this->P->cb_customdata['item'] = $this->admin_prepareItem($aItemdata);
112
                    } else {
113
                        $this->P->cb_customdata['itemlist'] = $this->admin_prepareItemlist($aItemlist);
114
                    }
115
                }
116
            } elseif (isset($this->post['doaction']) && $this->post['doaction'] === 'edititem') {
117
                $this->admin_updateItem();
118
                $this->P->cb_customdata['itemupdated'] = true;
119
120
                $aItemdata = $this->admin_getItem();
121
                $this->P->cb_customdata['item'] = $this->admin_prepareItem($aItemdata);
122
            } elseif ($this->get['action'] === 'showitem') {
123
                $aItemdata = $this->admin_getItem();
124
                $this->P->cb_customdata['item'] = $this->admin_prepareItem($aItemdata);
125
            } elseif ($this->get['action'] === 'additem') {
126
                $aErr = [];
127
                if (isset($this->post['additem']) && $this->post['additem'] === 'do') {
128
                    if (strlen($this->post['itemno']) < 4) {
129
                        $aErr['itemnotooshort'] = true;
130
                    } else {
131
                        $querybuilder = $this->dbal->createQueryBuilder();
132
                        $querybuilder
133
                            ->select('itm_no')
134
                            ->from('item_base')
135
                            ->where('itm_no = ?')
136
                            ->setParameter(0, trim(filter_input(INPUT_POST, 'itemno', FILTER_SANITIZE_SPECIAL_CHARS)))
137
                        ;
138
                        $stmt = $querybuilder->execute();
139
140
                        if ($stmt->rowCount() > 0) {
141
                            $aErr['itemnoalreadytaken'] = true;
142
                        } else {
143
                            $querybuilder = $this->dbal->createQueryBuilder();
144
                            $querybuilder
145
                                ->insert('item_base')
146
                                ->setValue('itm_no', '?')
147
                                ->setParameter(0, trim(filter_input(INPUT_POST, 'itemno', FILTER_SANITIZE_SPECIAL_CHARS)))
148
                            ;
149
150
                            $querybuilder->execute();
151
                            $iInsertID = $this->dbal->lastInsertId();
152
153
                            $queryBuilder = $this->dbal->createQueryBuilder();
154
                            $queryBuilder
155
                                ->select('itm_no')
156
                                ->from('item_base')
157
                                ->where('itm_id = '.$queryBuilder->createNamedParameter($iInsertID))
158
                            ;
159
                            $statement = $queryBuilder->execute();
160
                            $row = $statement->fetch();
161
162
                            \HaaseIT\HCSF\Helper::redirectToPage('/_admin/itemadmin.html?itemno='.$row['itm_no'].'&action=showitem');
163
                        }
164
                    }
165
                }
166
                $this->P->cb_customdata['showaddform'] = true;
167
                $this->P->cb_customdata['err'] = $aErr;
168
            }
169
        }
170
    }
171
172
    /**
173
     * @return mixed
174
     */
175
    private function admin_prepareItemlistsearchform()
0 ignored issues
show
Coding Style introduced by
admin_prepareItemlistsearchform 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...
176
    {
177
        $aData['searchcats'] = [
0 ignored issues
show
Coding Style Comprehensibility introduced by
$aData was never initialized. Although not strictly required by PHP, it is generally a good practice to add $aData = 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
            'nummer|'.HardcodedText::get('itemadmin_search_itemno'),
179
            'name|'.HardcodedText::get('itemadmin_search_itemname'),
180
            'index|'.HardcodedText::get('itemadmin_search_itemindex'),
181
        ];
182
        $aData['orderbys'] = [
183
            'nummer|'.HardcodedText::get('itemadmin_search_itemno'),
184
            'name|'.HardcodedText::get('itemadmin_search_itemname'),
185
        ];
186
187 View Code Duplication
        if (isset($this->get['searchcat'])) {
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...
188
            $aData['searchcat'] = $this->get['searchcat'];
189
            $_SESSION['itemadmin_searchcat'] = $this->get['searchcat'];
190
        } elseif (isset($_SESSION['itemadmin_searchcat'])) {
191
            $aData['searchcat'] = $_SESSION['itemadmin_searchcat'];
192
        }
193
194 View Code Duplication
        if (isset($this->get['orderby'])) {
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...
195
            $aData['orderby'] = $this->get['orderby'];
196
            $_SESSION['itemadmin_orderby'] = $this->get['orderby'];
197
        } elseif (isset($_SESSION['itemadmin_orderby'])) {
198
            $aData['orderby'] = $_SESSION['itemadmin_orderby'];
199
        }
200
201
        return $aData;
202
    }
203
204
    /**
205
     * @return bool
206
     */
207
    private function admin_getItemlist()
208
    {
209
        $sSearchstring = filter_input(INPUT_GET, 'searchstring', FILTER_SANITIZE_SPECIAL_CHARS);
210
        $sSearchstring = str_replace('*', '%', $sSearchstring);
211
212
        $querybuilder = $this->dbal->createQueryBuilder();
213
        $querybuilder
214
            ->select('itm_no, itm_name, itm_index')
215
            ->from('item_base', 'b')
216
            ->leftJoin('b', 'item_lang', 'l', 'b.itm_id = l.itml_pid AND l.itml_lang = :lang')
217
        ;
218
219
        if ($this->get['searchcat'] === 'name') {
220
            $querybuilder->where('itm_name LIKE :searchstring');
221
        } elseif ($this->get['searchcat'] === 'nummer') {
222
            $querybuilder->where('itm_no LIKE :searchstring');
223
        } elseif ($this->get['searchcat'] === 'index') {
224
            $querybuilder->where('itm_index LIKE :searchstring');
225
        } else {
226
            exit;
227
        }
228
229
        if ($this->get['orderby'] === 'name') {
230
            $querybuilder->orderBy('itm_name');
231
        } elseif ($this->get['orderby'] === 'nummer') {
232
            $querybuilder->orderBy('itm_no');
233
        }
234
235
        $querybuilder
236
            ->setParameter(':searchstring', $sSearchstring)
237
            ->setParameter(':lang', HelperConfig::$lang)
238
        ;
239
240
        $stmt = $querybuilder->execute();
241
242
        $aItemlist['numrows'] = $stmt->rowCount();
243
244
        if ($aItemlist['numrows'] !== 0) {
245
            while ($aRow = $stmt->fetch()) {
246
                $aItemlist['data'][] = $aRow;
247
            }
248
            return $aItemlist;
249
        }
250
251
        return false;
252
    }
253
254
    /**
255
     * @param $aItemlist
256
     * @return array
257
     */
258
    private function admin_prepareItemlist($aItemlist)
259
    {
260
        $aList = [
261
            ['title' => HardcodedText::get('itemadmin_list_active'), 'key' => 'itemindex', 'width' => 30, 'linked' => false, 'callback' => 'renderItemStatusIcon',],
262
            ['title' => HardcodedText::get('itemadmin_list_itemno'), 'key' => 'itemno', 'width' => 100, 'linked' => false,],
263
            ['title' => HardcodedText::get('itemadmin_list_name'), 'key' => 'name', 'width' => 350, 'linked' => false,],
264
            ['title' => HardcodedText::get('itemadmin_list_edit'), 'key' => 'itemno', 'width' => 30, 'linked' => true, 'ltarget' => '/_admin/itemadmin.html', 'lkeyname' => 'itemno', 'lgetvars' => ['action' => 'showitem'],],
265
        ];
266
        $aData = [];
267
        foreach ($aItemlist['data'] as $aValue) {
268
            $aData[] = [
269
                'itemindex' => $aValue['itm_index'],
270
                'itemno' => $aValue['itm_no'],
271
                'name' => $aValue['itm_name'],
272
            ];
273
        }
274
275
        return [
276
            'numrows' => $aItemlist['numrows'],
277
            'listtable' => Tools::makeListtable($aList, $aData, $this->serviceManager->get('twig')),
278
        ];
279
    }
280
281
    /**
282
     * @param string $sItemno
283
     * @return bool
284
     */
285
    private function admin_getItem($sItemno = '')
286
    {
287
        if ($sItemno === '') {
288
            if (empty($this->get['itemno'])) {
289
                return false;
290
            }
291
            $sItemno = filter_var($this->get['itemno'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
292
        }
293
294
        $querybuilder = $this->dbal->createQueryBuilder();
295
        $querybuilder
296
            ->select('*')
297
            ->from('item_base')
298
            ->where('itm_no = ?')
299
            ->setParameter(0, $sItemno)
300
        ;
301
        $stmt = $querybuilder->execute();
302
303
        $aItemdata['base'] = $stmt->fetch();
304
305
        $querybuilder = $this->dbal->createQueryBuilder();
306
        $querybuilder
307
            ->select('*')
308
            ->from('item_lang')
309
            ->where('itml_pid = ? AND itml_lang = ?')
310
            ->setParameter(0, $aItemdata['base']['itm_id'])
311
            ->setParameter(1, HelperConfig::$lang)
312
        ;
313
        $stmt = $querybuilder->execute();
314
315
        if ($stmt->rowCount() != 0) {
316
            $aItemdata['text'] = $stmt->fetch();
317
        }
318
319
        return $aItemdata;
320
    }
321
322
    /**
323
     * @param $aItemdata
324
     * @return array
325
     */
326
    private function admin_prepareItem($aItemdata)
327
    {
328
        $aData = [
329
            'form' => ['action' => Tools::makeLinkHRefWithAddedGetVars('/_admin/itemadmin.html', ['action' => 'showitem', 'itemno' => $aItemdata['base']['itm_no']]),],
330
            'id' => $aItemdata['base']['itm_id'],
331
            'itemno' => $aItemdata['base']['itm_no'],
332
            'name' => $aItemdata['base']['itm_name'],
333
            'img' => $aItemdata['base']['itm_img'],
334
            'price' => $aItemdata['base']['itm_price'],
335
            'vatid' => $aItemdata['base']['itm_vatid'],
336
            'rg' => $aItemdata['base']['itm_rg'],
337
            'index' => $aItemdata['base']['itm_index'],
338
            'prio' => $aItemdata['base']['itm_order'],
339
            'group' => $aItemdata['base']['itm_group'],
340
            'data' => $aItemdata['base']['itm_data'],
341
            'weight' => $aItemdata['base']['itm_weight'],
342
        ];
343
344
        if (!HelperConfig::$shop['vat_disable']) {
345
            $aOptions[] = '|';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$aOptions was never initialized. Although not strictly required by PHP, it is generally a good practice to add $aOptions = 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...
346
            foreach (HelperConfig::$shop['vat'] as $sKey => $sValue) {
347
                $aOptions[] = $sKey.'|'.$sValue;
348
            }
349
            $aData['vatoptions'] = $aOptions;
350
            unset($aOptions);
351
        }
352
        $aData['rgoptions'][] = '';
353
        foreach (HelperConfig::$shop['rebate_groups'] as $sKey => $aValue) {
354
            $aData['rgoptions'][] = $sKey;
355
        }
356
357
        $aGroups = $this->admin_getItemgroups('');
358
        $aData['groupoptions'][] = '';
359
        foreach ($aGroups as $aValue) {
360
            $aData['groupoptions'][] = $aValue['itmg_id'] . '|' . $aValue['itmg_no'] . ' - ' . $aValue['itmg_name'];
361
        }
362
        unset($aGroups);
363
364
        if (isset($aItemdata['text'])) {
365
            $aData['lang'] = [
366
                'textid' => $aItemdata['text']['itml_id'],
367
                'nameoverride' => $aItemdata['text']['itml_name_override'],
368
                'text1' => $aItemdata['text']['itml_text1'],
369
                'text2' => $aItemdata['text']['itml_text2'],
370
            ];
371
        }
372
373
        return $aData;
374
    }
375
376
    /**
377
     * @return bool
378
     */
379
    private function admin_updateItem()
380
    {
381
        $purifier = false;
382
        if (HelperConfig::$shop['itemtext_enable_purifier']) {
383
            $purifier = \HaaseIT\HCSF\Helper::getPurifier('item');
384
        }
385
386
        $querybuilder = $this->dbal->createQueryBuilder();
387
        $querybuilder
388
            ->update('item_base')
389
            ->set('itm_name', ':itm_name')
390
            ->set('itm_group', ':itm_group')
391
            ->set('itm_img', ':itm_img')
392
            ->set('itm_index', ':itm_index')
393
            ->set('itm_order', ':itm_order')
394
            ->set('itm_price', ':itm_price')
395
            ->set('itm_rg', ':itm_rg')
396
            ->set('itm_data', ':itm_data')
397
            ->set('itm_weight', ':itm_weight')
398
            ->set('itm_vatid', ':itm_vatid')
399
            ->where('itm_id = :itm_id')
400
            ->setParameter(':itm_name', filter_var($this->post['name'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW))
401
            ->setParameter(':itm_group', filter_var($this->post['group'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW))
402
            ->setParameter(':itm_img', filter_var($this->post['bild'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW))
403
            ->setParameter(':itm_index', filter_var($this->post['index'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW))
404
            ->setParameter(':itm_order', filter_var($this->post['prio'], FILTER_SANITIZE_NUMBER_INT))
405
            ->setParameter(':itm_price', filter_var($this->post['price'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION))
406
            ->setParameter(':itm_rg', filter_var($this->post['rg'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW))
407
            ->setParameter(':itm_data', filter_var($this->post['data'], FILTER_UNSAFE_RAW))
408
            ->setParameter(':itm_weight', filter_var($this->post['weight'], FILTER_SANITIZE_NUMBER_INT))
409
            ->setParameter(':itm_id', filter_var($this->post['id'], FILTER_SANITIZE_NUMBER_INT))
410
        ;
411
412
        if (!HelperConfig::$shop['vat_disable']) {
413
            $querybuilder->setParameter(':itm_vatid', filter_var($this->post['vatid'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW));
414
        } else {
415
            $querybuilder->setParameter(':itm_vatid', 'full');
416
        }
417
        $querybuilder->execute();
418
419
        if (isset($this->post['textid'])) {
420
            $querybuilder = $this->dbal->createQueryBuilder();
421
            $querybuilder
422
                ->update('item_lang')
423
                ->set('itml_text1', ':itml_text1')
424
                ->set('itml_text2', ':itml_text2')
425
                ->set('itml_name_override', ':itml_name_override')
426
                ->where('itml_id = :itml_id')
427
                ->setParameter(':itml_text1', !empty($this->purifier) ? $purifier->purify($this->post['text1']) : $this->post['text1'])
428
                ->setParameter(':itml_text2', !empty($this->purifier) ? $purifier->purify($this->post['text2']) : $this->post['text2'])
429
                ->setParameter(':itml_name_override', filter_var($this->post['name_override'], FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW))
430
                ->setParameter(':itml_id', filter_var($this->post['textid'], FILTER_SANITIZE_NUMBER_INT))
431
            ;
432
            $querybuilder->execute();
433
        }
434
435
        return true;
436
    }
437
438
    /**
439
     * @param string $iGID
440
     * @return mixed
441
     */
442
    private function admin_getItemgroups($iGID = '') // this function should be outsourced, a duplicate is used in admin itemgroups!
443
    {
444
        $querybuilder = $this->dbal->createQueryBuilder();
445
        $querybuilder
446
            ->select('*')
447
            ->from('itemgroups_base', 'b')
448
            ->leftJoin('b', 'itemgroups_text', 't', 'b.itmg_id = t.itmgt_pid AND t.itmgt_lang = ?')
449
            ->setParameter(0, HelperConfig::$lang)
450
            ->orderBy('itmg_no')
451
        ;
452
453
        if ($iGID != '') {
454
            $querybuilder
455
                ->where('itmg_id = :gid')
456
                ->setParameter(1, $iGID)
457
            ;
458
        }
459
        $stmt = $querybuilder->execute();
460
461
        return $stmt->fetchAll();
462
    }
463
}
464