Completed
Push — master ( 5d6df6...4b07ef )
by Arnold
03:18
created

EventDispatcher::off()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 11
nc 2
nop 1
dl 0
loc 18
ccs 12
cts 12
cp 1
crap 3
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Jasny\EventDispatcher;
6
7
use Improved as i;
8
use Improved\IteratorPipeline\Pipeline;
9
use function Jasny\str_contains;
10
11
/**
12
 * Event dispatcher.
13
 * @immutable
14
 */
15
class EventDispatcher
16
{
17
    /**
18
     * @var array
19
     */
20
    protected $triggers = [];
21
22
23
    /**
24
     * Bind a handler for an event.
25
     *
26
     * @param string   $event
27
     * @param callable $handler
28
     * @return static
29
     */
30 2
    public function on(string $event, callable $handler): self
31
    {
32 2
        if (str_contains($event, '*')) {
33 1
            throw new \InvalidArgumentException("Invalid event name '$event': illegal character '*'");
34
        }
35
36 1
        $clone = clone $this;
37 1
        $clone->triggers[] = ['event' => $event, 'handler' => $handler];
38
39 1
        return $clone;
40
    }
41
42
    /**
43
     * Unbind a handler of an event.
44
     *
45
     * @param string $event  Event name, optionally with wildcards
46
     * @return $this
47
     */
48 3
    public function off(string $event): self
49
    {
50 3
        $triggers = Pipeline::with($this->triggers)
51
            ->filter(function ($trigger) use ($event) {
52 3
                return !fnmatch($event, $trigger['event'], FNM_NOESCAPE)
53 3
                    && !fnmatch("$event.*", $trigger['event'], FNM_NOESCAPE);
54 3
            })
55 3
            ->values()
56 3
            ->toArray();
57
58 3
        if (count($triggers) === count($this->triggers)) {
59 3
            return $this;
60
        }
61
62 3
        $clone = clone $this;
63 3
        $clone->triggers = $triggers;
64
65 3
        return $clone;
66
    }
67
68
69
    /**
70
     * Trigger an event.
71
     *
72
     * @param string $event
73
     * @param object $subject
74
     * @param mixed  $payload
75
     * @return mixed
76
     */
77 1
    public function trigger(string $event, $subject, $payload = null)
78
    {
79 1
        return Pipeline::with($this->triggers)
80
            ->filter(function ($trigger) use ($event) {
81 1
                return $event ===  $trigger['event'] || fnmatch("{$event}.*", $trigger['event'], FNM_NOESCAPE);
82 1
            })
83 1
            ->column('handler')
84
            ->reduce(function ($payload, $handler) use ($subject) {
85 1
                return i\function_call($handler, $subject, $payload);
0 ignored issues
show
Bug introduced by
The function function_call was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

85
                return /** @scrutinizer ignore-call */ i\function_call($handler, $subject, $payload);
Loading history...
86 1
            }, $payload);
87
    }
88
}
89