Passed
Push — 1.0 ( e29635...abd87a )
by
unknown
02:59
created

ShoppingCart   B

Complexity

Total Complexity 47

Size/Duplication

Total Lines 461
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 165
dl 0
loc 461
rs 8.64
c 0
b 0
f 0
wmc 47

21 Methods

Rating   Name   Duplication   Size   Complexity  
A setDataRecord() 0 4 1
A DiscountForm() 0 25 1
B usediscount() 0 25 7
B doUpdate() 0 37 9
A ShowTax() 0 4 1
A CartForm() 0 17 1
A getMenu() 0 5 2
A getMetaTitle() 0 3 1
A index() 0 5 1
A Link() 0 5 1
A init() 0 20 6
A getTitle() 0 6 2
A remove() 0 25 3
A RelativeLink() 0 5 1
A emptycart() 0 11 1
A checkout() 0 13 2
A doAddDiscount() 0 12 2
A getDataRecord() 0 3 1
A Menu() 0 3 1
A AbsoluteLink() 0 3 1
A PostageForm() 0 21 2

How to fix   Complexity   

Complex Class

Complex classes like ShoppingCart often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ShoppingCart, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace SilverCommerce\ShoppingCart\Control;
4
5
use SilverStripe\i18n\i18n;
6
use SilverStripe\Forms\Form;
7
use SilverStripe\View\SSViewer;
8
use SilverStripe\Forms\FieldList;
9
use SilverStripe\Forms\TextField;
10
use SilverStripe\Control\Director;
11
use SilverStripe\Forms\FormAction;
12
use SilverStripe\Control\Controller;
13
use SilverStripe\ORM\ValidationResult;
14
use SilverStripe\SiteConfig\SiteConfig;
15
use SilverStripe\Core\Injector\Injector;
16
use SilverStripe\Subsites\Model\Subsite;
0 ignored issues
show
Bug introduced by
The type SilverStripe\Subsites\Model\Subsite was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
use SilverStripe\ORM\ValidationException;
18
use SilverCommerce\Discounts\Model\Discount;
19
use SilverCommerce\Checkout\Control\Checkout;
0 ignored issues
show
Bug introduced by
The type SilverCommerce\Checkout\Control\Checkout was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
20
use SilverCommerce\Postage\Forms\PostageForm;
21
use SilverCommerce\OrdersAdmin\Model\Estimate;
22
use SilverStripe\CMS\Controllers\ContentController;
0 ignored issues
show
Bug introduced by
The type SilverStripe\CMS\Controllers\ContentController was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
23
use SilverCommerce\ShoppingCart\ShoppingCartFactory;
24
25
/**
26
 * Holder for items in the shopping cart and interacting with them, as
27
 * well as rendering these items into an interface that allows editing
28
 * of items,
29
 *
30
 * @author ilateral (http://www.ilateral.co.uk)
31
 * @package shoppingcart
32
 */
33
class ShoppingCart extends Controller
34
{
35
36
    /**
37
     * URL Used to access this controller
38
     *
39
     * @var string
40
     * @config
41
     */
42
    private static $url_segment = 'shoppingcart';
43
44
    /**
45
     * Setup default templates for this controller
46
     *
47
     * @var array
48
     */
49
    protected $templates = [
50
        "index" => [ShoppingCart::class, "Page"],
51
        "usediscount" => [ShoppingCart::class . "_usediscount", ShoppingCart::class, "Page"]
52
    ];
53
    
54
    /**
55
     * Overwrite the default title for this controller which is taken
56
     * from the translation files. This is used for Title and MetaTitle
57
     * variables in templates.
58
     *
59
     * @var string
60
     * @config
61
     */
62
    private static $title;
63
64
    /**
65
     * Class Name of object we use as an assotiated estimate.
66
     * This defaults to Estimate
67
     *
68
     * @var string
69
     * @config
70
     */
71
    private static $checkout_class = Checkout::class;
72
73
    /**
74
     * Redirect the user to the cart when an item is added?
75
     * 
76
     * @var boolean
77
     */
78
    private static $redirect_on_add = false;
0 ignored issues
show
introduced by
The private property $redirect_on_add is not used, and could be removed.
Loading history...
79
80
    /**
81
     * The associated dataRecord
82
     *
83
     * @var ShoppingCartModel
0 ignored issues
show
Bug introduced by
The type SilverCommerce\ShoppingC...ntrol\ShoppingCartModel was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
84
     */
85
    protected $dataRecord;
86
87
    /**
88
     * These methods are mapped to sub URLs of this
89
     * controller.
90
     *
91
     * @var array
92
     */
93
    private static $allowed_actions = [
0 ignored issues
show
introduced by
The private property $allowed_actions is not used, and could be removed.
Loading history...
94
        "remove",
95
        "emptycart",
96
        "usediscount",
97
        "setdeliverytype",
98
        "checkout",
99
        "CartForm",
100
        "PostageForm",
101
        "DiscountForm"
102
    ];
103
104
    /**
105
     * Overwrite default init to support subsites (if installed)
106
     * 
107
     * @return void 
108
     */
109
    protected function init()
110
    {
111
        parent::init();
112
113
        // Setup current controller on init (as Security::getMember()
114
        // is not available on construction)
115
        $dataRecord = ShoppingCartFactory::create()->getCurrent();
116
        $this->setDataRecord($dataRecord);
117
        $this->setFailover($this->dataRecord);
118
119
        # Check for subsites and add support
120
        if (class_exists(Subsite::class)) {
121
            $subsite = Subsite::currentSubsite();
122
123
            if ($subsite && $subsite->Theme) {
124
                SSViewer::add_themes([$subsite->Theme]);
125
            }
126
127
            if ($subsite && i18n::getData()->validate($subsite->Language)) {
128
                i18n::set_locale($subsite->Language);
129
            }
130
        }
131
    }
132
    
133
    public function getTitle()
134
    {
135
        if ($this->config()->title) {
136
            return $this->config()->title;
137
        } else {
138
            _t("SilverCommerce\ShoppingCart.CartName", "Shopping Cart");
139
        }
140
    }
141
142
    public function getMetaTitle()
143
    {
144
        return $this->getTitle();
145
    }
146
147
    public function getDataRecord()
148
    {
149
        return $this->dataRecord;
150
    }
151
152
    public function setDataRecord($record)
153
    {
154
        $this->dataRecord = $record;
155
        return $this;
156
    }
157
158
    /**
159
     * Get the link to this controller
160
     *
161
     * @param string $action The action you want to add to the link
162
     * @return string
163
     */
164
    public function Link($action = null)
165
    {
166
        return Controller::join_links(
167
            $this->config()->url_segment,
168
            $action
169
        );
170
    }
171
172
    /**
173
     * Get an absolute link to this controller
174
     *
175
     * @param string $action The action you want to add to the link
176
     * @return string
177
     */
178
    public function AbsoluteLink($action = null)
179
    {
180
        return Director::absoluteURL($this->Link($action));
181
    }
182
183
    /**
184
     * Get a relative (to the root url of the site) link to this
185
     * controller
186
     *
187
     * @param string $action The action you want to add to the link
188
     * @return string
189
     */
190
    public function RelativeLink($action = null)
191
    {
192
        return Controller::join_links(
193
            Director::baseURL(),
194
            $this->Link($action)
195
        );
196
    }
197
198
    /**
199
     * If content controller exists, return it's menu function
200
     * @param int $level Menu level to return.
201
     * @return ArrayList
0 ignored issues
show
Bug introduced by
The type SilverCommerce\ShoppingCart\Control\ArrayList was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
202
     */
203
    public function getMenu($level = 1)
204
    {
205
        if (class_exists(ContentController::class)) {
206
            $controller = ContentController::singleton();
207
            return $controller->getMenu($level);
208
        }
209
    }
210
211
    public function Menu($level)
0 ignored issues
show
Unused Code introduced by
The parameter $level is not used and could be removed. ( Ignorable by Annotation )

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

211
    public function Menu(/** @scrutinizer ignore-unused */ $level)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
212
    {
213
        return $this->getMenu();
214
    }
215
216
    /**
217
     * Default acton for the shopping cart
218
     */
219
    public function index()
220
    {
221
        $this->extend("onBeforeIndex");
222
223
        return $this->render();
224
    }
225
226
    /**
227
     * Remove a product from ShoppingCart Via its ID. This action
228
     * expects an ID to be sent through the URL that matches a specific
229
     * key added to an item in the cart
230
     *
231
     * @return Redirect
0 ignored issues
show
Bug introduced by
The type SilverCommerce\ShoppingCart\Control\Redirect was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
232
     */
233
    public function remove()
234
    {
235
        $key = $this->request->param('ID');
236
        $item = null;
237
        $title = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $title is dead and can be removed.
Loading history...
238
239
        if (isset($key)) {
240
            $item = $this
241
                ->Items()
0 ignored issues
show
Bug introduced by
The method Items() does not exist on SilverCommerce\ShoppingCart\Control\ShoppingCart. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

241
                ->/** @scrutinizer ignore-call */ Items()
Loading history...
242
                ->find("Key", $key);
243
        }
244
245
        if (isset($item)) {
246
            $title = $item->Title;
247
            ShoppingCartFactory::create()->removeItem($item);
248
249
            $form = $this->CartForm();
250
            $form->sessionMessage(_t(
251
                "ShoppingCart.RemovedItem",
252
                "Removed '{title}' from your cart",
253
                ["title" => $title]
254
            ));
255
        }
256
257
        return $this->redirectBack();
258
    }
259
    
260
    /**
261
     * Action that will clear shopping cart and associated items
262
     *
263
     */
264
    public function emptycart()
265
    {
266
        ShoppingCartFactory::create()->delete();
267
        
268
        $form = $this->CartForm();
269
        $form->sessionMessage(_t(
270
            "ShoppingCart.EmptiedCart",
271
            "Shopping cart emptied"
272
        ));
273
274
        return $this->redirectBack();
275
    }
276
    
277
    
278
    /**
279
     * Action used to add a discount to the users session via a URL.
280
     * This is preferable to using the dicount form as disount code
281
     * forms seem to provide a less than perfect user experience
282
     *
283
     */
284
    public function usediscount()
285
    {   
286
        $code_to_search = $this->request->param("ID");
287
        $code = false;
288
        $curr = $this->getDiscount();
0 ignored issues
show
Bug introduced by
The method getDiscount() does not exist on SilverCommerce\ShoppingCart\Control\ShoppingCart. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

288
        /** @scrutinizer ignore-call */ 
289
        $curr = $this->getDiscount();
Loading history...
289
        
290
        if (!$code_to_search) {
291
            return $this->httpError(404, "Page not found");
292
        }
293
        
294
        // First check if the discount is already added (so we don't
295
        // query the DB if we don't have to).
296
        if (!$curr || ($curr && $curr->Code != $code_to_search)) {
297
            $this->setDiscount($code_to_search);
0 ignored issues
show
Bug introduced by
The method setDiscount() does not exist on SilverCommerce\ShoppingCart\Control\ShoppingCart. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

297
            $this->/** @scrutinizer ignore-call */ 
298
                   setDiscount($code_to_search);
Loading history...
298
            ShoppingCartFactory::create()->save();
299
        } elseif ($curr && $code->Code == $code_to_search) {
0 ignored issues
show
Bug introduced by
The property Code does not exist on false.
Loading history...
300
            $code = $this->getDiscount();
301
        }
302
303
        $this->extend("onBeforeUseDiscount");
304
305
        return $this
306
            ->customise([
307
                "Discount" => $code
308
            ])->render();
309
    }
310
311
    /**
312
     * Setup the checkout and redirect to it
313
     *
314
     * @return Redirect
315
     */
316
    public function checkout()
317
    {
318
        if (!class_exists($this->config()->checkout_class)) {
319
            return $this->httpError(404);
320
        }
321
322
        $checkout = Injector::inst()
323
            ->get($this->config()->checkout_class);
324
        $checkout->setEstimate($this->dataRecord);
325
326
        $this->extend("onBeforeCheckout");
327
328
        $this->redirect($checkout->Link());
329
    }
330
    
331
    /**
332
     * Shortcut to checkout config, to allow us to access it via
333
     * templates
334
     *
335
     * @return boolean
336
     */
337
    public function ShowTax()
338
    {
339
        $config = SiteConfig::current_site_config();
340
        return $config->ShowPriceAndTax;
341
    }
342
343
    /**
344
     * Form responsible for listing items in the shopping cart and
345
     * allowing management (such as addition, removal, etc)
346
     *
347
     * @return Form
348
     */
349
    public function CartForm()
350
    {   
351
        $form = Form::create(
352
            $this,
353
            "CartForm",
354
            FieldList::create(),
355
            FieldList::create(
356
                FormAction::create(
357
                    'doUpdate',
358
                    _t('ShoppingCart.UpdateCart', 'Update Cart')
359
                )->addExtraClass('btn btn-info')
360
            )
361
        )->setTemplate("SilverCommerce\ShoppingCart\Forms\Includes\ShoppingCartForm");
362
        
363
        $this->extend("updateCartForm", $form);
364
        
365
        return $form;
366
    }
367
    
368
    /**
369
     * Form that allows you to add a discount code which then gets added
370
     * to the cart's list of discounts.
371
     *
372
     * @return Form
373
     */
374
    public function DiscountForm()
375
    {
376
        $form = Form::create(
377
            $this,
378
            "DiscountForm",
379
            FieldList::create(
380
                TextField::create(
381
                    "DiscountCode",
382
                    _t("ShoppingCart.DiscountCode", "Discount Code")
383
                )->setAttribute(
384
                    "placeholder",
385
                    _t("ShoppingCart.EnterDiscountCode", "Enter a discount code")
386
                )
387
            ),
388
            FieldList::create(
389
                FormAction::create(
390
                    'doAddDiscount',
391
                    _t('ShoppingCart.Add', 'Add')
392
                )->addExtraClass('btn btn-info')
393
            )
394
        );
395
        
396
        $this->extend("updateDiscountForm", $form);
397
        
398
        return $form;
399
    }
400
    
401
    /**
402
     * Form responsible for estimating shipping based on location and
403
     * postal code
404
     *
405
     * @return Form
406
     */
407
    public function PostageForm()
408
    {
409
        if ($this->isDeliverable()) {
0 ignored issues
show
Bug introduced by
The method isDeliverable() does not exist on SilverCommerce\ShoppingCart\Control\ShoppingCart. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

409
        if ($this->/** @scrutinizer ignore-call */ isDeliverable()) {
Loading history...
410
            $form = PostageForm::create(
411
                $this,
412
                "PostageForm",
413
                $this->dataRecord,
414
                $this->dataRecord->SubTotal,
415
                $this->dataRecord->TotalWeight,
416
                $this->dataRecord->TotalItems
417
            );
418
419
            $form->setLegend(_t(
420
                "SilverCommerce\ShoppingCart.EstimatePostage",
421
                "Estimate Postage"
422
            ));
423
424
            // Extension call
425
            $this->extend("updatePostageForm", $form);
426
427
            return $form;
428
        }
429
    }
430
431
    /**
432
     * Action that will update cart
433
     *
434
     * @param type $data
435
     * @param type $form
0 ignored issues
show
Bug introduced by
The type SilverCommerce\ShoppingCart\Control\type was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
436
     */
437
    public function doUpdate($data, $form)
438
    {
439
        try {
440
            foreach ($this->Items() as $item) {
441
                foreach ($data as $key => $value) {
442
                    $sliced_key = explode("_", $key);
443
                    if ($sliced_key[0] == "Quantity") {
444
                        if (isset($item) && ($item->Key == $sliced_key[1])) {
445
                            if ($value > 0) {
446
                                ShoppingCartFactory::create()->updateItem(
447
                                    $item,
448
                                    $value
449
                                );
450
                            } else {
451
                                $item->delete();
452
                            }
453
454
                            $form->sessionMessage(
455
                                _t("ShoppingCart.UpdatedShoppingCart", "Shopping cart updated"),
456
                                ValidationResult::TYPE_GOOD
457
                            );
458
                        }
459
                    }
460
                }
461
            }
462
            ShoppingCartFactory::create()->save();
463
        } catch (ValidationException $e) {
464
            $form->sessionMessage(
465
                $e->getMessage()
466
            );
467
        } catch (Exception $e) {
0 ignored issues
show
Bug introduced by
The type SilverCommerce\ShoppingCart\Control\Exception was not found. Did you mean Exception? If so, make sure to prefix the type with \.
Loading history...
468
            $form->sessionMessage(
469
                $e->getMessage()
470
            );
471
        }
472
        
473
        return $this->redirectBack();
474
    }
475
    
476
    /**
477
     * Action that will find a discount based on the code
478
     *
479
     * @param type $data
480
     * @param type $form
481
     */
482
    public function doAddDiscount($data, $form)
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed. ( Ignorable by Annotation )

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

482
    public function doAddDiscount($data, /** @scrutinizer ignore-unused */ $form)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
483
    {
484
        $code_to_search = $data['DiscountCode'];
485
        
486
        // First check if the discount is already added (so we don't
487
        // query the DB if we don't have to).
488
        if ($this->getDiscount()->Code != $code_to_search) {
489
            $this->setDiscount($code_to_search);
490
            ShoppingCartFactory::create()->save();
491
        }
492
        
493
        return $this->redirectBack();
494
    }
495
}
496