Completed
Push — master ( a262cd...27e755 )
by darryl
10s
created

Cart   C

Complexity

Total Complexity 74

Size/Duplication

Total Lines 757
Duplicated Lines 2.38 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 8
Bugs 2 Features 1
Metric Value
wmc 74
c 8
b 2
f 1
lcom 1
cbo 8
dl 18
loc 757
rs 5

34 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 10 1
A getInstanceName() 0 4 1
A get() 0 4 1
A has() 0 4 1
B add() 0 57 5
C update() 0 45 8
B addItemCondition() 0 26 4
A remove() 0 15 2
A clear() 0 14 2
B condition() 0 30 6
A getConditions() 0 4 1
A getCondition() 0 4 1
A getConditionsByType() 0 6 1
A removeConditionsByType() 0 6 1
A removeCartCondition() 0 8 1
C removeItemCondition() 0 50 8
A clearItemConditions() 0 12 2
A clearCartConditions() 0 7 1
A getSubTotal() 0 10 1
B getTotal() 0 31 3
A getTotalQuantity() 0 12 2
A getContent() 0 4 1
A isEmpty() 0 6 1
A validate() 17 17 2
A addRow() 0 16 2
A save() 0 4 1
A saveConditions() 0 4 1
A itemHasConditions() 0 14 4
A updateQuantityRelative() 0 18 4
A updateQuantityNotRelative() 0 6 1
A setDecimals() 0 4 1
A setDecPoint() 0 4 1
A setThousandsSep() 0 4 1
A fireEvent() 0 4 1

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

1
<?php namespace Darryldecode\Cart;
2
3
use Darryldecode\Cart\Exceptions\InvalidConditionException;
4
use Darryldecode\Cart\Exceptions\InvalidItemException;
5
use Darryldecode\Cart\Helpers\Helpers;
6
use Darryldecode\Cart\Validators\CartItemValidator;
7
8
/**
9
 * Class Cart
10
 * @package Darryldecode\Cart
11
 */
12
class Cart
13
{
14
15
    /**
16
     * the item storage
17
     *
18
     * @var
19
     */
20
    protected $session;
21
22
    /**
23
     * the event dispatcher
24
     *
25
     * @var
26
     */
27
    protected $events;
28
29
    /**
30
     * the cart session key
31
     *
32
     * @var
33
     */
34
    protected $instanceName;
35
36
    /**
37
     * the session key use to persist cart items
38
     *
39
     * @var
40
     */
41
    protected $sessionKeyCartItems;
42
43
    /**
44
     * the session key use to persist cart conditions
45
     *
46
     * @var
47
     */
48
    protected $sessionKeyCartConditions;
49
50
    /**
51
     * Configuration to pass to ItemCollection
52
     *
53
     * @var
54
     */
55
    protected $config;
56
57
    /**
58
     * our object constructor
59
     *
60
     * @param $session
61
     * @param $events
62
     * @param $instanceName
63
     * @param $session_key
64
     * @param $config
65
     */
66
    public function __construct($session, $events, $instanceName, $session_key, $config)
67
    {
68
        $this->events = $events;
69
        $this->session = $session;
70
        $this->instanceName = $instanceName;
71
        $this->sessionKeyCartItems = $session_key . '_cart_items';
72
        $this->sessionKeyCartConditions = $session_key . '_cart_conditions';
73
        $this->fireEvent('created');
74
        $this->config = $config;
75
    }
76
77
    /**
78
     * get instance name of the cart
79
     *
80
     * @return string
81
     */
82
    public function getInstanceName()
83
    {
84
        return $this->instanceName;
85
    }
86
87
    /**
88
     * get an item on a cart by item ID
89
     *
90
     * @param $itemId
91
     * @return mixed
92
     */
93
    public function get($itemId)
94
    {
95
        return $this->getContent()->get($itemId);
96
    }
97
98
    /**
99
     * check if an item exists by item ID
100
     *
101
     * @param $itemId
102
     * @return bool
103
     */
104
    public function has($itemId)
105
    {
106
        return $this->getContent()->has($itemId);
107
    }
108
109
    /**
110
     * add item to the cart, it can be an array or multi dimensional array
111
     *
112
     * @param string|array $id
113
     * @param string $name
114
     * @param float $price
115
     * @param int $quantity
116
     * @param array $attributes
117
     * @param CartCondition|array $conditions
118
     * @return $this
119
     * @throws InvalidItemException
120
     */
121
    public function add($id, $name = null, $price = null, $quantity = null, $attributes = array(), $conditions = array())
122
    {
123
        // if the first argument is an array,
124
        // we will need to call add again
125
        if (is_array($id)) {
126
            // the first argument is an array, now we will need to check if it is a multi dimensional
127
            // array, if so, we will iterate through each item and call add again
128
            if (Helpers::isMultiArray($id)) {
129
                foreach ($id as $item) {
130
                    $this->add(
131
                        $item['id'],
132
                        $item['name'],
133
                        $item['price'],
134
                        $item['quantity'],
135
                        Helpers::issetAndHasValueOrAssignDefault($item['attributes'], array()),
136
                        Helpers::issetAndHasValueOrAssignDefault($item['conditions'], array())
137
                    );
138
                }
139
            } else {
140
                $this->add(
141
                    $id['id'],
142
                    $id['name'],
143
                    $id['price'],
144
                    $id['quantity'],
145
                    Helpers::issetAndHasValueOrAssignDefault($id['attributes'], array()),
146
                    Helpers::issetAndHasValueOrAssignDefault($id['conditions'], array())
147
                );
148
            }
149
150
            return $this;
151
        }
152
153
        // validate data
154
        $item = $this->validate(array(
155
            'id' => $id,
156
            'name' => $name,
157
            'price' => Helpers::normalizePrice($price),
158
            'quantity' => $quantity,
159
            'attributes' => new ItemAttributeCollection($attributes),
160
            'conditions' => $conditions,
161
        ));
162
163
        // get the cart
164
        $cart = $this->getContent();
165
166
        // if the item is already in the cart we will just update it
167
        if ($cart->has($id)) {
168
169
            $this->update($id, $item);
170
        } else {
171
172
            $this->addRow($id, $item);
173
174
        }
175
176
        return $this;
177
    }
178
179
    /**
180
     * update a cart
181
     *
182
     * @param $id
183
     * @param $data
184
     *
185
     * the $data will be an associative array, you don't need to pass all the data, only the key value
186
     * of the item you want to update on it
187
     * @return bool
188
     */
189
    public function update($id, $data)
190
    {
191
        if($this->fireEvent('updating', $data) === false) {
192
            return false;
193
        }
194
195
        $cart = $this->getContent();
196
197
        $item = $cart->pull($id);
198
199
        foreach ($data as $key => $value) {
200
            // if the key is currently "quantity" we will need to check if an arithmetic
201
            // symbol is present so we can decide if the update of quantity is being added
202
            // or being reduced.
203
            if ($key == 'quantity') {
204
                // we will check if quantity value provided is array,
205
                // if it is, we will need to check if a key "relative" is set
206
                // and we will evaluate its value if true or false,
207
                // this tells us how to treat the quantity value if it should be updated
208
                // relatively to its current quantity value or just totally replace the value
209
                if (is_array($value)) {
210
                    if (isset($value['relative'])) {
211
                        if ((bool)$value['relative']) {
212
                            $item = $this->updateQuantityRelative($item, $key, $value['value']);
213
                        } else {
214
                            $item = $this->updateQuantityNotRelative($item, $key, $value['value']);
215
                        }
216
                    }
217
                } else {
218
                    $item = $this->updateQuantityRelative($item, $key, $value);
219
                }
220
            } elseif ($key == 'attributes') {
221
                $item[$key] = new ItemAttributeCollection($value);
222
            } else {
223
                $item[$key] = $value;
224
            }
225
        }
226
227
        $cart->put($id, $item);
228
229
        $this->save($cart);
230
231
        $this->fireEvent('updated', $item);
232
        return true;
233
    }
234
235
    /**
236
     * add condition on an existing item on the cart
237
     *
238
     * @param int|string $productId
239
     * @param CartCondition $itemCondition
240
     * @return $this
241
     */
242
    public function addItemCondition($productId, $itemCondition)
243
    {
244
        if ($product = $this->get($productId)) {
245
            $conditionInstance = "\\Darryldecode\\Cart\\CartCondition";
246
247
            if ($itemCondition instanceof $conditionInstance) {
248
                // we need to copy first to a temporary variable to hold the conditions
249
                // to avoid hitting this error "Indirect modification of overloaded element of Darryldecode\Cart\ItemCollection has no effect"
250
                // this is due to laravel Collection instance that implements Array Access
251
                // // see link for more info: http://stackoverflow.com/questions/20053269/indirect-modification-of-overloaded-element-of-splfixedarray-has-no-effect
252
                $itemConditionTempHolder = $product['conditions'];
253
254
                if (is_array($itemConditionTempHolder)) {
255
                    array_push($itemConditionTempHolder, $itemCondition);
256
                } else {
257
                    $itemConditionTempHolder = $itemCondition;
258
                }
259
260
                $this->update($productId, array(
261
                    'conditions' => $itemConditionTempHolder // the newly updated conditions
262
                ));
263
            }
264
        }
265
266
        return $this;
267
    }
268
269
    /**
270
     * removes an item on cart by item ID
271
     *
272
     * @param $id
273
     * @return bool
274
     */
275
    public function remove($id)
276
    {
277
        $cart = $this->getContent();
278
279
        if($this->fireEvent('removing', $id) === false) {
280
            return false;
281
        }
282
283
        $cart->forget($id);
284
285
        $this->save($cart);
286
287
        $this->fireEvent('removed', $id);
288
        return true;
289
    }
290
291
    /**
292
     * clear cart
293
     * @return bool
294
     */
295
    public function clear()
296
    {
297
        if($this->fireEvent('clearing') === false) {
298
            return false;
299
        }
300
301
        $this->session->put(
302
            $this->sessionKeyCartItems,
303
            array()
304
        );
305
306
        $this->fireEvent('cleared');
307
        return true;
308
    }
309
310
    /**
311
     * add a condition on the cart
312
     *
313
     * @param CartCondition|array $condition
314
     * @return $this
315
     * @throws InvalidConditionException
316
     */
317
    public function condition($condition)
318
    {
319
        if (is_array($condition)) {
320
            foreach ($condition as $c) {
321
                $this->condition($c);
322
            }
323
324
            return $this;
325
        }
326
327
        if (!$condition instanceof CartCondition) throw new InvalidConditionException('Argument 1 must be an instance of \'Darryldecode\Cart\CartCondition\'');
328
329
        $conditions = $this->getConditions();
330
331
        // Check if order has been applied
332
        if ($condition->getOrder() == 0) {
333
            $last = $conditions->last();
334
            $condition->setOrder(!is_null($last) ? $last->getOrder() + 1 : 1);
335
        }
336
337
        $conditions->put($condition->getName(), $condition);
338
339
        $conditions = $conditions->sortBy(function ($condition, $key) {
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed.

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

Loading history...
340
            return $condition->getOrder();
341
        });
342
343
        $this->saveConditions($conditions);
344
345
        return $this;
346
    }
347
348
    /**
349
     * get conditions applied on the cart
350
     *
351
     * @return CartConditionCollection
352
     */
353
    public function getConditions()
354
    {
355
        return new CartConditionCollection($this->session->get($this->sessionKeyCartConditions));
356
    }
357
358
    /**
359
     * get condition applied on the cart by its name
360
     *
361
     * @param $conditionName
362
     * @return CartCondition
363
     */
364
    public function getCondition($conditionName)
365
    {
366
        return $this->getConditions()->get($conditionName);
367
    }
368
369
    /**
370
     * Get all the condition filtered by Type
371
     * Please Note that this will only return condition added on cart bases, not those conditions added
372
     * specifically on an per item bases
373
     *
374
     * @param $type
375
     * @return CartConditionCollection
376
     */
377
    public function getConditionsByType($type)
378
    {
379
        return $this->getConditions()->filter(function (CartCondition $condition) use ($type) {
380
            return $condition->getType() == $type;
381
        });
382
    }
383
384
385
    /**
386
     * Remove all the condition with the $type specified
387
     * Please Note that this will only remove condition added on cart bases, not those conditions added
388
     * specifically on an per item bases
389
     *
390
     * @param $type
391
     * @return $this
392
     */
393
    public function removeConditionsByType($type)
394
    {
395
        $this->getConditionsByType($type)->each(function ($condition) {
396
            $this->removeCartCondition($condition->getName());
397
        });
398
    }
399
400
401
    /**
402
     * removes a condition on a cart by condition name,
403
     * this can only remove conditions that are added on cart bases not conditions that are added on an item/product.
404
     * If you wish to remove a condition that has been added for a specific item/product, you may
405
     * use the removeItemCondition(itemId, conditionName) method instead.
406
     *
407
     * @param $conditionName
408
     * @return void
409
     */
410
    public function removeCartCondition($conditionName)
411
    {
412
        $conditions = $this->getConditions();
413
414
        $conditions->pull($conditionName);
415
416
        $this->saveConditions($conditions);
417
    }
418
419
    /**
420
     * remove a condition that has been applied on an item that is already on the cart
421
     *
422
     * @param $itemId
423
     * @param $conditionName
424
     * @return bool
425
     */
426
    public function removeItemCondition($itemId, $conditionName)
427
    {
428
        if (!$item = $this->getContent()->get($itemId)) {
429
            return false;
430
        }
431
432
        if ($this->itemHasConditions($item)) {
433
            // NOTE:
434
            // we do it this way, we get first conditions and store
435
            // it in a temp variable $originalConditions, then we will modify the array there
436
            // and after modification we will store it again on $item['conditions']
437
            // This is because of ArrayAccess implementation
438
            // see link for more info: http://stackoverflow.com/questions/20053269/indirect-modification-of-overloaded-element-of-splfixedarray-has-no-effect
439
440
            $tempConditionsHolder = $item['conditions'];
441
442
            // if the item's conditions is in array format
443
            // we will iterate through all of it and check if the name matches
444
            // to the given name the user wants to remove, if so, remove it
445
            if (is_array($tempConditionsHolder)) {
446
                foreach ($tempConditionsHolder as $k => $condition) {
447
                    if ($condition->getName() == $conditionName) {
448
                        unset($tempConditionsHolder[$k]);
449
                    }
450
                }
451
452
                $item['conditions'] = $tempConditionsHolder;
453
            }
454
455
            // if the item condition is not an array, we will check if it is
456
            // an instance of a Condition, if so, we will check if the name matches
457
            // on the given condition name the user wants to remove, if so,
458
            // lets just make $item['conditions'] an empty array as there's just 1 condition on it anyway
459
            else {
460
                $conditionInstance = "Darryldecode\\Cart\\CartCondition";
461
462
                if ($item['conditions'] instanceof $conditionInstance) {
463
                    if ($tempConditionsHolder->getName() == $conditionName) {
464
                        $item['conditions'] = array();
465
                    }
466
                }
467
            }
468
        }
469
470
        $this->update($itemId, array(
471
            'conditions' => $item['conditions']
472
        ));
473
474
        return true;
475
    }
476
477
    /**
478
     * remove all conditions that has been applied on an item that is already on the cart
479
     *
480
     * @param $itemId
481
     * @return bool
482
     */
483
    public function clearItemConditions($itemId)
484
    {
485
        if (!$item = $this->getContent()->get($itemId)) {
486
            return false;
487
        }
488
489
        $this->update($itemId, array(
490
            'conditions' => array()
491
        ));
492
493
        return true;
494
    }
495
496
    /**
497
     * clears all conditions on a cart,
498
     * this does not remove conditions that has been added specifically to an item/product.
499
     * If you wish to remove a specific condition to a product, you may use the method: removeItemCondition($itemId, $conditionName)
500
     *
501
     * @return void
502
     */
503
    public function clearCartConditions()
504
    {
505
        $this->session->put(
506
            $this->sessionKeyCartConditions,
507
            array()
508
        );
509
    }
510
511
    /**
512
     * get cart sub total
513
     * @param bool $formatted
514
     * @return float
515
     */
516
    public function getSubTotal($formatted = true)
517
    {
518
        $cart = $this->getContent();
519
520
        $sum = $cart->sum(function ($item) {
521
            return $item->getPriceSumWithConditions(false);
522
        });
523
524
        return Helpers::formatValue(floatval($sum), $formatted, $this->config);
525
    }
526
527
    /**
528
     * the new total in which conditions are already applied
529
     *
530
     * @return float
531
     */
532
    public function getTotal()
533
    {
534
        $subTotal = $this->getSubTotal(false);
535
536
        $newTotal = 0.00;
537
538
        $process = 0;
539
540
        $conditions = $this
541
            ->getConditions()
542
            ->filter(function ($cond) {
543
                return $cond->getTarget() === 'subtotal';
544
            });
545
546
        // if no conditions were added, just return the sub total
547
        if (!$conditions->count()) {
548
            return Helpers::formatValue($subTotal, $this->config['format_numbers'], $this->config);
549
        }
550
551
        $conditions
552
            ->each(function ($cond) use ($subTotal, &$newTotal, &$process) {
553
                $toBeCalculated = ($process > 0) ? $newTotal : $subTotal;
554
555
                $newTotal = $cond->applyCondition($toBeCalculated);
556
557
                $process++;
558
559
            });
560
561
        return Helpers::formatValue($newTotal, $this->config['format_numbers'], $this->config);
562
    }
563
564
    /**
565
     * get total quantity of items in the cart
566
     *
567
     * @return int
568
     */
569
    public function getTotalQuantity()
570
    {
571
        $items = $this->getContent();
572
573
        if ($items->isEmpty()) return 0;
574
575
        $count = $items->sum(function ($item) {
576
            return $item['quantity'];
577
        });
578
579
        return $count;
580
    }
581
582
    /**
583
     * get the cart
584
     *
585
     * @return CartCollection
586
     */
587
    public function getContent()
588
    {
589
        return (new CartCollection($this->session->get($this->sessionKeyCartItems)));
590
    }
591
592
    /**
593
     * check if cart is empty
594
     *
595
     * @return bool
596
     */
597
    public function isEmpty()
598
    {
599
        $cart = new CartCollection($this->session->get($this->sessionKeyCartItems));
600
601
        return $cart->isEmpty();
602
    }
603
604
    /**
605
     * validate Item data
606
     *
607
     * @param $item
608
     * @return array $item;
609
     * @throws InvalidItemException
610
     */
611 View Code Duplication
    protected function validate($item)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
612
    {
613
        $rules = array(
614
            'id' => 'required',
615
            'price' => 'required|numeric',
616
            'quantity' => 'required|numeric|min:1',
617
            'name' => 'required',
618
        );
619
620
        $validator = CartItemValidator::make($item, $rules);
621
622
        if ($validator->fails()) {
623
            throw new InvalidItemException($validator->messages()->first());
624
        }
625
626
        return $item;
627
    }
628
629
    /**
630
     * add row to cart collection
631
     *
632
     * @param $id
633
     * @param $item
634
     * @return bool
635
     */
636
    protected function addRow($id, $item)
637
    {
638
        if($this->fireEvent('adding', $item) === false) {
639
            return false;
640
        }
641
642
        $cart = $this->getContent();
643
644
        $cart->put($id, new ItemCollection($item, $this->config));
645
646
        $this->save($cart);
647
648
        $this->fireEvent('added', $item);
649
650
        return true;
651
    }
652
653
    /**
654
     * save the cart
655
     *
656
     * @param $cart CartCollection
657
     */
658
    protected function save($cart)
659
    {
660
        $this->session->put($this->sessionKeyCartItems, $cart);
661
    }
662
663
    /**
664
     * save the cart conditions
665
     *
666
     * @param $conditions
667
     */
668
    protected function saveConditions($conditions)
669
    {
670
        $this->session->put($this->sessionKeyCartConditions, $conditions);
671
    }
672
673
    /**
674
     * check if an item has condition
675
     *
676
     * @param $item
677
     * @return bool
678
     */
679
    protected function itemHasConditions($item)
680
    {
681
        if (!isset($item['conditions'])) return false;
682
683
        if (is_array($item['conditions'])) {
684
            return count($item['conditions']) > 0;
685
        }
686
687
        $conditionInstance = "Darryldecode\\Cart\\CartCondition";
688
689
        if ($item['conditions'] instanceof $conditionInstance) return true;
690
691
        return false;
692
    }
693
694
    /**
695
     * update a cart item quantity relative to its current quantity
696
     *
697
     * @param $item
698
     * @param $key
699
     * @param $value
700
     * @return mixed
701
     */
702
    protected function updateQuantityRelative($item, $key, $value)
703
    {
704
        if (preg_match('/\-/', $value) == 1) {
705
            $value = (int)str_replace('-', '', $value);
706
707
            // we will not allowed to reduced quantity to 0, so if the given value
708
            // would result to item quantity of 0, we will not do it.
709
            if (($item[$key] - $value) > 0) {
710
                $item[$key] -= $value;
711
            }
712
        } elseif (preg_match('/\+/', $value) == 1) {
713
            $item[$key] += (int)str_replace('+', '', $value);
714
        } else {
715
            $item[$key] += (int)$value;
716
        }
717
718
        return $item;
719
    }
720
721
    /**
722
     * update cart item quantity not relative to its current quantity value
723
     *
724
     * @param $item
725
     * @param $key
726
     * @param $value
727
     * @return mixed
728
     */
729
    protected function updateQuantityNotRelative($item, $key, $value)
730
    {
731
        $item[$key] = (int)$value;
732
733
        return $item;
734
    }
735
736
    /**
737
     * Setter for decimals. Change value on demand.
738
     * @param $decimals
739
     */
740
    public function setDecimals($decimals)
741
    {
742
        $this->decimals = $decimals;
0 ignored issues
show
Bug introduced by
The property decimals does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
743
    }
744
745
    /**
746
     * Setter for decimals point. Change value on demand.
747
     * @param $dec_point
748
     */
749
    public function setDecPoint($dec_point)
750
    {
751
        $this->dec_point = $dec_point;
0 ignored issues
show
Bug introduced by
The property dec_point does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
752
    }
753
754
    public function setThousandsSep($thousands_sep)
755
    {
756
        $this->thousands_sep = $thousands_sep;
0 ignored issues
show
Bug introduced by
The property thousands_sep does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
757
    }
758
759
    /**
760
     * @param $name
761
     * @param $value
762
     * @return mixed
763
     */
764
    protected function fireEvent($name, $value = [])
765
    {
766
        return $this->events->fire($this->getInstanceName() . '.' . $name, array_values([$value, $this]));
767
    }
768
}
769