Completed
Pull Request — master (#187)
by
unknown
01:12
created

Cart::getTotalQuantityIndividual()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
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 for the cart
38
     *
39
     * @var
40
     */
41
    protected $sessionKey;
42
43
    /**
44
     * the session key use to persist cart items
45
     *
46
     * @var
47
     */
48
    protected $sessionKeyCartItems;
49
50
    /**
51
     * the session key use to persist cart conditions
52
     *
53
     * @var
54
     */
55
    protected $sessionKeyCartConditions;
56
57
    /**
58
     * Configuration to pass to ItemCollection
59
     *
60
     * @var
61
     */
62
    protected $config;
63
64
    /**
65
     * our object constructor
66
     *
67
     * @param $session
68
     * @param $events
69
     * @param $instanceName
70
     * @param $session_key
71
     * @param $config
72
     */
73
    public function __construct($session, $events, $instanceName, $session_key, $config)
74
    {
75
        $this->events = $events;
76
        $this->session = $session;
77
        $this->instanceName = $instanceName;
78
        $this->sessionKey = $session_key;
79
        $this->sessionKeyCartItems = $this->sessionKey . '_cart_items';
80
        $this->sessionKeyCartConditions = $this->sessionKey . '_cart_conditions';
81
        $this->config = $config;
82
        $this->fireEvent('created');
83
    }
84
85
    /**
86
     * sets the session key
87
     *
88
     * @param string $sessionKey the session key or identifier
89
     * @return $this|bool
90
     * @throws \Exception
91
     */
92
    public function session($sessionKey)
93
    {
94
        if(!$sessionKey) throw new \Exception("Session key is required.");
95
96
        $this->sessionKey = $sessionKey;
97
        $this->sessionKeyCartItems = $this->sessionKey . '_cart_items';
98
        $this->sessionKeyCartConditions = $this->sessionKey . '_cart_conditions';
99
100
        return $this;
101
    }
102
103
    /**
104
     * get instance name of the cart
105
     *
106
     * @return string
107
     */
108
    public function getInstanceName()
109
    {
110
        return $this->instanceName;
111
    }
112
113
    /**
114
     * get an item on a cart by item ID
115
     *
116
     * @param $itemId
117
     * @return mixed
118
     */
119
    public function get($itemId)
120
    {
121
        return $this->getContent()->get($itemId);
122
    }
123
124
    /**
125
     * check if an item exists by item ID
126
     *
127
     * @param $itemId
128
     * @return bool
129
     */
130
    public function has($itemId)
131
    {
132
        return $this->getContent()->has($itemId);
133
    }
134
135
    /**
136
     * add item to the cart, it can be an array or multi dimensional array
137
     *
138
     * @param string|array $id
139
     * @param string $name
140
     * @param float $price
141
     * @param int $quantity
142
     * @param array $attributes
143
     * @param CartCondition|array $conditions
144
     * @return $this
145
     * @throws InvalidItemException
146
     */
147
    public function add($id, $name = null, $price = null, $quantity = null, $attributes = array(), $conditions = array())
148
    {
149
        // if the first argument is an array,
150
        // we will need to call add again
151
        if (is_array($id)) {
152
            // the first argument is an array, now we will need to check if it is a multi dimensional
153
            // array, if so, we will iterate through each item and call add again
154
            if (Helpers::isMultiArray($id)) {
155
                foreach ($id as $item) {
156
                    $this->add(
157
                        $item['id'],
158
                        $item['name'],
159
                        $item['price'],
160
                        $item['quantity'],
161
                        Helpers::issetAndHasValueOrAssignDefault($item['attributes'], array()),
162
                        Helpers::issetAndHasValueOrAssignDefault($item['conditions'], array())
163
                    );
164
                }
165
            } else {
166
                $this->add(
167
                    $id['id'],
168
                    $id['name'],
169
                    $id['price'],
170
                    $id['quantity'],
171
                    Helpers::issetAndHasValueOrAssignDefault($id['attributes'], array()),
172
                    Helpers::issetAndHasValueOrAssignDefault($id['conditions'], array())
173
                );
174
            }
175
176
            return $this;
177
        }
178
179
        // validate data
180
        $item = $this->validate(array(
181
            'id' => $id,
182
            'name' => $name,
183
            'price' => Helpers::normalizePrice($price),
184
            'quantity' => $quantity,
185
            'attributes' => new ItemAttributeCollection($attributes),
186
            'conditions' => $conditions,
187
        ));
188
189
        // get the cart
190
        $cart = $this->getContent();
191
192
        // if the item is already in the cart we will just update it
193
        if ($cart->has($id)) {
194
195
            $this->update($id, $item);
196
        } else {
197
198
            $this->addRow($id, $item);
199
200
        }
201
202
        return $this;
203
    }
204
205
    /**
206
     * update a cart
207
     *
208
     * @param $id
209
     * @param $data
210
     *
211
     * the $data will be an associative array, you don't need to pass all the data, only the key value
212
     * of the item you want to update on it
213
     * @return bool
214
     */
215
    public function update($id, $data)
216
    {
217
        if($this->fireEvent('updating', $data) === false) {
218
            return false;
219
        }
220
221
        $cart = $this->getContent();
222
223
        $item = $cart->pull($id);
224
225
        foreach ($data as $key => $value) {
226
            // if the key is currently "quantity" we will need to check if an arithmetic
227
            // symbol is present so we can decide if the update of quantity is being added
228
            // or being reduced.
229
            if ($key == 'quantity') {
230
                // we will check if quantity value provided is array,
231
                // if it is, we will need to check if a key "relative" is set
232
                // and we will evaluate its value if true or false,
233
                // this tells us how to treat the quantity value if it should be updated
234
                // relatively to its current quantity value or just totally replace the value
235
                if (is_array($value)) {
236
                    if (isset($value['relative'])) {
237
                        if ((bool)$value['relative']) {
238
                            $item = $this->updateQuantityRelative($item, $key, $value['value']);
239
                        } else {
240
                            $item = $this->updateQuantityNotRelative($item, $key, $value['value']);
241
                        }
242
                    }
243
                } else {
244
                    $item = $this->updateQuantityRelative($item, $key, $value);
245
                }
246
            } elseif ($key == 'attributes') {
247
                $item[$key] = new ItemAttributeCollection($value);
248
            } else {
249
                $item[$key] = $value;
250
            }
251
        }
252
253
        $cart->put($id, $item);
254
255
        $this->save($cart);
256
257
        $this->fireEvent('updated', $item);
258
        return true;
259
    }
260
261
    /**
262
     * add condition on an existing item on the cart
263
     *
264
     * @param int|string $productId
265
     * @param CartCondition $itemCondition
266
     * @return $this
267
     */
268
    public function addItemCondition($productId, $itemCondition)
269
    {
270
        if ($product = $this->get($productId)) {
271
            $conditionInstance = "\\Darryldecode\\Cart\\CartCondition";
272
273
            if ($itemCondition instanceof $conditionInstance) {
274
                // we need to copy first to a temporary variable to hold the conditions
275
                // to avoid hitting this error "Indirect modification of overloaded element of Darryldecode\Cart\ItemCollection has no effect"
276
                // this is due to laravel Collection instance that implements Array Access
277
                // // see link for more info: http://stackoverflow.com/questions/20053269/indirect-modification-of-overloaded-element-of-splfixedarray-has-no-effect
278
                $itemConditionTempHolder = $product['conditions'];
279
280
                if (is_array($itemConditionTempHolder)) {
281
                    array_push($itemConditionTempHolder, $itemCondition);
282
                } else {
283
                    $itemConditionTempHolder = $itemCondition;
284
                }
285
286
                $this->update($productId, array(
287
                    'conditions' => $itemConditionTempHolder // the newly updated conditions
288
                ));
289
            }
290
        }
291
292
        return $this;
293
    }
294
295
    /**
296
     * removes an item on cart by item ID
297
     *
298
     * @param $id
299
     * @return bool
300
     */
301
    public function remove($id)
302
    {
303
        $cart = $this->getContent();
304
305
        if($this->fireEvent('removing', $id) === false) {
306
            return false;
307
        }
308
309
        $cart->forget($id);
310
311
        $this->save($cart);
312
313
        $this->fireEvent('removed', $id);
314
        return true;
315
    }
316
317
    /**
318
     * clear cart
319
     * @return bool
320
     */
321
    public function clear()
322
    {
323
        if($this->fireEvent('clearing') === false) {
324
            return false;
325
        }
326
327
        $this->session->put(
328
            $this->sessionKeyCartItems,
329
            array()
330
        );
331
332
        $this->fireEvent('cleared');
333
        return true;
334
    }
335
336
    /**
337
     * add a condition on the cart
338
     *
339
     * @param CartCondition|array $condition
340
     * @return $this
341
     * @throws InvalidConditionException
342
     */
343
    public function condition($condition)
344
    {
345
        if (is_array($condition)) {
346
            foreach ($condition as $c) {
347
                $this->condition($c);
348
            }
349
350
            return $this;
351
        }
352
353
        if (!$condition instanceof CartCondition) throw new InvalidConditionException('Argument 1 must be an instance of \'Darryldecode\Cart\CartCondition\'');
354
355
        $conditions = $this->getConditions();
356
357
        // Check if order has been applied
358
        if ($condition->getOrder() == 0) {
359
            $last = $conditions->last();
360
            $condition->setOrder(!is_null($last) ? $last->getOrder() + 1 : 1);
361
        }
362
363
        $conditions->put($condition->getName(), $condition);
364
365
        $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...
366
            return $condition->getOrder();
367
        });
368
369
        $this->saveConditions($conditions);
370
371
        return $this;
372
    }
373
374
    /**
375
     * get conditions applied on the cart
376
     *
377
     * @return CartConditionCollection
378
     */
379
    public function getConditions()
380
    {
381
        return new CartConditionCollection($this->session->get($this->sessionKeyCartConditions));
382
    }
383
384
    /**
385
     * get condition applied on the cart by its name
386
     *
387
     * @param $conditionName
388
     * @return CartCondition
389
     */
390
    public function getCondition($conditionName)
391
    {
392
        return $this->getConditions()->get($conditionName);
393
    }
394
395
    /**
396
     * Get all the condition filtered by Type
397
     * Please Note that this will only return condition added on cart bases, not those conditions added
398
     * specifically on an per item bases
399
     *
400
     * @param $type
401
     * @return CartConditionCollection
402
     */
403
    public function getConditionsByType($type)
404
    {
405
        return $this->getConditions()->filter(function (CartCondition $condition) use ($type) {
406
            return $condition->getType() == $type;
407
        });
408
    }
409
410
411
    /**
412
     * Remove all the condition with the $type specified
413
     * Please Note that this will only remove condition added on cart bases, not those conditions added
414
     * specifically on an per item bases
415
     *
416
     * @param $type
417
     * @return $this
418
     */
419
    public function removeConditionsByType($type)
420
    {
421
        $this->getConditionsByType($type)->each(function ($condition) {
422
            $this->removeCartCondition($condition->getName());
423
        });
424
    }
425
426
427
    /**
428
     * removes a condition on a cart by condition name,
429
     * this can only remove conditions that are added on cart bases not conditions that are added on an item/product.
430
     * If you wish to remove a condition that has been added for a specific item/product, you may
431
     * use the removeItemCondition(itemId, conditionName) method instead.
432
     *
433
     * @param $conditionName
434
     * @return void
435
     */
436
    public function removeCartCondition($conditionName)
437
    {
438
        $conditions = $this->getConditions();
439
440
        $conditions->pull($conditionName);
441
442
        $this->saveConditions($conditions);
443
    }
444
445
    /**
446
     * remove a condition that has been applied on an item that is already on the cart
447
     *
448
     * @param $itemId
449
     * @param $conditionName
450
     * @return bool
451
     */
452
    public function removeItemCondition($itemId, $conditionName)
453
    {
454
        if (!$item = $this->getContent()->get($itemId)) {
455
            return false;
456
        }
457
458
        if ($this->itemHasConditions($item)) {
459
            // NOTE:
460
            // we do it this way, we get first conditions and store
461
            // it in a temp variable $originalConditions, then we will modify the array there
462
            // and after modification we will store it again on $item['conditions']
463
            // This is because of ArrayAccess implementation
464
            // see link for more info: http://stackoverflow.com/questions/20053269/indirect-modification-of-overloaded-element-of-splfixedarray-has-no-effect
465
466
            $tempConditionsHolder = $item['conditions'];
467
468
            // if the item's conditions is in array format
469
            // we will iterate through all of it and check if the name matches
470
            // to the given name the user wants to remove, if so, remove it
471
            if (is_array($tempConditionsHolder)) {
472
                foreach ($tempConditionsHolder as $k => $condition) {
473
                    if ($condition->getName() == $conditionName) {
474
                        unset($tempConditionsHolder[$k]);
475
                    }
476
                }
477
478
                $item['conditions'] = $tempConditionsHolder;
479
            }
480
481
            // if the item condition is not an array, we will check if it is
482
            // an instance of a Condition, if so, we will check if the name matches
483
            // on the given condition name the user wants to remove, if so,
484
            // lets just make $item['conditions'] an empty array as there's just 1 condition on it anyway
485
            else {
486
                $conditionInstance = "Darryldecode\\Cart\\CartCondition";
487
488
                if ($item['conditions'] instanceof $conditionInstance) {
489
                    if ($tempConditionsHolder->getName() == $conditionName) {
490
                        $item['conditions'] = array();
491
                    }
492
                }
493
            }
494
        }
495
496
        $this->update($itemId, array(
497
            'conditions' => $item['conditions']
498
        ));
499
500
        return true;
501
    }
502
503
    /**
504
     * remove all conditions that has been applied on an item that is already on the cart
505
     *
506
     * @param $itemId
507
     * @return bool
508
     */
509
    public function clearItemConditions($itemId)
510
    {
511
        if (!$item = $this->getContent()->get($itemId)) {
512
            return false;
513
        }
514
515
        $this->update($itemId, array(
516
            'conditions' => array()
517
        ));
518
519
        return true;
520
    }
521
522
    /**
523
     * clears all conditions on a cart,
524
     * this does not remove conditions that has been added specifically to an item/product.
525
     * If you wish to remove a specific condition to a product, you may use the method: removeItemCondition($itemId, $conditionName)
526
     *
527
     * @return void
528
     */
529
    public function clearCartConditions()
530
    {
531
        $this->session->put(
532
            $this->sessionKeyCartConditions,
533
            array()
534
        );
535
    }
536
537
    /**
538
     * get cart sub total without conditions
539
     * @param bool $formatted
540
     * @return float
541
     */
542
    public function getSubTotalWithoutConditions($formatted = true)
543
    {
544
        $cart = $this->getContent();
545
546
        $sum = $cart->sum(function ($item) {
547
            return $item->getPriceSum(false);
548
        });
549
550
        return Helpers::formatValue(floatval($sum), $formatted, $this->config);
551
    }    
552
    
553
    /**
554
     * get cart sub total
555
     * @param bool $formatted
556
     * @return float
557
     */
558
    public function getSubTotal($formatted = true)
559
    {
560
        $cart = $this->getContent();
561
562
        $sum = $cart->sum(function (ItemCollection $item) {
563
            return $item->getPriceSumWithConditions(false);
564
        });
565
566
        // get the conditions that are meant to be applied
567
        // on the subtotal and apply it here before returning the subtotal
568
        $conditions = $this
569
            ->getConditions()
570
            ->filter(function (CartCondition $cond) {
571
                return $cond->getTarget() === 'subtotal';
572
            });
573
574
        // if there is no conditions, lets just return the sum
575
        if(!$conditions->count()) return Helpers::formatValue(floatval($sum), $formatted, $this->config);
576
577
        // there are conditions, lets apply it
578
        $newTotal = 0.00;
579
        $process = 0;
580
581 View Code Duplication
        $conditions->each(function (CartCondition $cond) use ($sum, &$newTotal, &$process) {
582
583
            // if this is the first iteration, the toBeCalculated
584
            // should be the sum as initial point of value.
585
            $toBeCalculated = ($process > 0) ? $newTotal : $sum;
586
587
            $newTotal = $cond->applyCondition($toBeCalculated);
588
589
            $process++;
590
        });
591
592
        return Helpers::formatValue(floatval($newTotal), $formatted, $this->config);
593
    }
594
595
    /**
596
     * the new total in which conditions are already applied
597
     *
598
     * @return float
599
     */
600
    public function getTotal()
601
    {
602
        $subTotal = $this->getSubTotal(false);
603
604
        $newTotal = 0.00;
605
606
        $process = 0;
607
608
        $conditions = $this
609
            ->getConditions()
610
            ->filter(function (CartCondition $cond) {
611
                return $cond->getTarget() === 'total';
612
            });
613
614
        // if no conditions were added, just return the sub total
615
        if (!$conditions->count()) {
616
            return Helpers::formatValue($subTotal, $this->config['format_numbers'], $this->config);
617
        }
618
619
        $conditions
620 View Code Duplication
            ->each(function (CartCondition $cond) use ($subTotal, &$newTotal, &$process) {
621
                $toBeCalculated = ($process > 0) ? $newTotal : $subTotal;
622
623
                $newTotal = $cond->applyCondition($toBeCalculated);
624
625
                $process++;
626
627
            });
628
629
        return Helpers::formatValue($newTotal, $this->config['format_numbers'], $this->config);
630
    }
631
632
    /**
633
     * get total quantity of items in the cart
634
     *
635
     * @return int
636
     */
637
    public function getTotalQuantity()
638
    {
639
        $items = $this->getContent();
640
641
        if ($items->isEmpty()) return 0;
642
643
        $count = $items->sum(function ($item) {
644
            return $item['quantity'];
645
        });
646
647
        return $count;
648
    }
649
650
    /**
651
     * get total quantity of items individual in the cart
652
     *
653
     * @return int
654
     */
655
    public function getTotalQuantityIndividual()
656
    {
657
        $items = $this->getContent();
658
659
        return $items->count();
660
    }
661
662
    /**
663
     * get the cart
664
     *
665
     * @return CartCollection
666
     */
667
    public function getContent()
668
    {
669
        return (new CartCollection($this->session->get($this->sessionKeyCartItems)));
670
    }
671
672
    /**
673
     * check if cart is empty
674
     *
675
     * @return bool
676
     */
677
    public function isEmpty()
678
    {
679
        $cart = new CartCollection($this->session->get($this->sessionKeyCartItems));
680
681
        return $cart->isEmpty();
682
    }
683
684
    /**
685
     * validate Item data
686
     *
687
     * @param $item
688
     * @return array $item;
689
     * @throws InvalidItemException
690
     */
691 View Code Duplication
    protected function validate($item)
692
    {
693
        $rules = array(
694
            'id' => 'required',
695
            'price' => 'required|numeric',
696
            'quantity' => 'required|numeric|min:1',
697
            'name' => 'required',
698
        );
699
700
        $validator = CartItemValidator::make($item, $rules);
701
702
        if ($validator->fails()) {
703
            throw new InvalidItemException($validator->messages()->first());
704
        }
705
706
        return $item;
707
    }
708
709
    /**
710
     * add row to cart collection
711
     *
712
     * @param $id
713
     * @param $item
714
     * @return bool
715
     */
716
    protected function addRow($id, $item)
717
    {
718
        if($this->fireEvent('adding', $item) === false) {
719
            return false;
720
        }
721
722
        $cart = $this->getContent();
723
724
        $cart->put($id, new ItemCollection($item, $this->config));
725
726
        $this->save($cart);
727
728
        $this->fireEvent('added', $item);
729
730
        return true;
731
    }
732
733
    /**
734
     * save the cart
735
     *
736
     * @param $cart CartCollection
737
     */
738
    protected function save($cart)
739
    {
740
        $this->session->put($this->sessionKeyCartItems, $cart);
741
    }
742
743
    /**
744
     * save the cart conditions
745
     *
746
     * @param $conditions
747
     */
748
    protected function saveConditions($conditions)
749
    {
750
        $this->session->put($this->sessionKeyCartConditions, $conditions);
751
    }
752
753
    /**
754
     * check if an item has condition
755
     *
756
     * @param $item
757
     * @return bool
758
     */
759
    protected function itemHasConditions($item)
760
    {
761
        if (!isset($item['conditions'])) return false;
762
763
        if (is_array($item['conditions'])) {
764
            return count($item['conditions']) > 0;
765
        }
766
767
        $conditionInstance = "Darryldecode\\Cart\\CartCondition";
768
769
        if ($item['conditions'] instanceof $conditionInstance) return true;
770
771
        return false;
772
    }
773
774
    /**
775
     * update a cart item quantity relative to its current quantity
776
     *
777
     * @param $item
778
     * @param $key
779
     * @param $value
780
     * @return mixed
781
     */
782
    protected function updateQuantityRelative($item, $key, $value)
783
    {
784
        if (preg_match('/\-/', $value) == 1) {
785
            $value = (int)str_replace('-', '', $value);
786
787
            // we will not allowed to reduced quantity to 0, so if the given value
788
            // would result to item quantity of 0, we will not do it.
789
            if (($item[$key] - $value) > 0) {
790
                $item[$key] -= $value;
791
            }
792
        } elseif (preg_match('/\+/', $value) == 1) {
793
            $item[$key] += (int)str_replace('+', '', $value);
794
        } else {
795
            $item[$key] += (int)$value;
796
        }
797
798
        return $item;
799
    }
800
801
    /**
802
     * update cart item quantity not relative to its current quantity value
803
     *
804
     * @param $item
805
     * @param $key
806
     * @param $value
807
     * @return mixed
808
     */
809
    protected function updateQuantityNotRelative($item, $key, $value)
810
    {
811
        $item[$key] = (int)$value;
812
813
        return $item;
814
    }
815
816
    /**
817
     * Setter for decimals. Change value on demand.
818
     * @param $decimals
819
     */
820
    public function setDecimals($decimals)
821
    {
822
        $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...
823
    }
824
825
    /**
826
     * Setter for decimals point. Change value on demand.
827
     * @param $dec_point
828
     */
829
    public function setDecPoint($dec_point)
830
    {
831
        $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...
832
    }
833
834
    public function setThousandsSep($thousands_sep)
835
    {
836
        $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...
837
    }
838
839
    /**
840
     * @param $name
841
     * @param $value
842
     * @return mixed
843
     */
844
    protected function fireEvent($name, $value = [])
845
    {
846
        return $this->events->dispatch($this->getInstanceName() . '.' . $name, array_values([$value, $this]));
847
    }
848
}
849