Completed
Push — master ( a00622...08b3e1 )
by Martin
14:53
created

Dispatcher   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 87
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 87
rs 10
wmc 15
lcom 1
cbo 1

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
B dispatch() 0 29 6
A acceptsMessage() 0 10 4
A getPluginMethods() 0 6 1
A removeUnsupportedMethods() 0 6 2
A debug() 0 5 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Spires\Core;
5
6
use Spires\Irc\Client;
7
use Spires\Irc\Message\Inbound\RawMessage;
8
use Spires\Contracts\Core\Core as SpiresCore;
9
10
class Dispatcher
11
{
12
13
    /**
14
     * @var Core
15
     */
16
    private $core;
17
18
    /**
19
     * @var int
20
     */
21
    private $indent = 0;
22
23
    public function __construct(SpiresCore $core)
24
    {
25
        $this->core = $core;
0 ignored issues
show
Documentation Bug introduced by
$core is of type object<Spires\Contracts\Core\Core>, but the property $core was declared to be of type object<Spires\Core\Core>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
26
    }
27
28
    public function dispatch($message)
29
    {
30
        $this->debug('━ Dispatching: [' . get_class($message) . ']');
31
        $this->core->instance(get_class($message), $message);
32
        $this->indent++;
33
        $enrichedMessages = [];
34
        foreach ($this->core->getPlugins() as $pluginClass => $pluginObject) {
35
            $methods = $this->getPluginMethods($pluginClass);
36
37
            foreach ($methods as $method) {
38
                if ($this->acceptsMessage($method, $message)) {
39
                    $this->debug('├ Calling: [' . $pluginClass . '@' . $method->getName() . ']');
40
                    $enrichedMessage = $this->core->call([$pluginObject, $method->name], [$message]);
41
                    if (!is_null($enrichedMessage)) {
42
                        $this->debug('├── Enriched message: [' . get_class($enrichedMessage) . ']');
43
                        $enrichedMessages[] = $enrichedMessage;
44
                    }
45
                }
46
            }
47
        }
48
49
        $this->debug('┕ Number of enriched messages to dispatch: ' . count($enrichedMessages));
50
        $this->indent++;
51
        foreach ($enrichedMessages as $enrichedMessage) {
52
            $this->dispatch($enrichedMessage);
53
        }
54
        $this->indent--;
55
        $this->indent--;
56
    }
57
58
    private function acceptsMessage(\ReflectionMethod $method, RawMessage $message) : bool
59
    {
60
        $parameters = $method->getParameters();
61
        foreach ($parameters as $parameter) {
62
            if ($parameter->getClass() && $parameter->getClass()->name === get_class($message)) {
63
                return true;
64
            }
65
        }
66
        return false;
67
    }
68
69
    /**
70
     * @param string $pluginClass
71
     * @return \ReflectionMethod[]
72
     */
73
    private function getPluginMethods(string $pluginClass) : array
74
    {
75
        return $this->removeUnsupportedMethods(
76
            (new \ReflectionClass($pluginClass))->getMethods()
77
        );
78
    }
79
80
    /**
81
     * @param \ReflectionMethod[] $methods
82
     * @return \ReflectionMethod[]
83
     */
84
    private function removeUnsupportedMethods(array $methods) : array
85
    {
86
        return array_filter($methods, function (\ReflectionMethod $method) {
87
            return $method->isPublic() && !$method->isStatic();
88
        });
89
    }
90
91
    private function debug(string $message)
92
    {
93
        $indention = str_repeat(' ', $this->indent*2);
94
        $this->core->make(Client::class)->logDebug($indention . $message);
95
    }
96
}
97