Dispatcher::dispatch()   B
last analyzed

Complexity

Conditions 6
Paths 10

Size

Total Lines 29
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 20
c 0
b 0
f 0
nc 10
nop 1
dl 0
loc 29
rs 8.439
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
     * @var Core
14
     */
15
    private $core;
16
17
    /**
18
     * @var int
19
     */
20
    private $indent = 0;
21
22
    public function __construct(SpiresCore $core)
23
    {
24
        $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...
25
    }
26
27
    public function dispatch($message)
28
    {
29
        $this->debug('━ Dispatching: [' . get_class($message) . ']');
30
        $this->core->instance(get_class($message), $message);
31
        $this->indent++;
32
        $enrichedMessages = [];
33
        foreach ($this->core->getPlugins() as $pluginClass => $pluginObject) {
34
            $methods = $this->getPluginMethods($pluginClass);
35
36
            foreach ($methods as $method) {
37
                if ($this->acceptsMessage($method, $message)) {
38
                    $this->debug('├ Calling: [' . $pluginClass . '@' . $method->getName() . ']');
39
                    $enrichedMessage = $this->core->call([$pluginObject, $method->name], [$message]);
40
                    if (!is_null($enrichedMessage)) {
41
                        $this->debug('├── Enriched message: [' . get_class($enrichedMessage) . ']');
42
                        $enrichedMessages[] = $enrichedMessage;
43
                    }
44
                }
45
            }
46
        }
47
48
        $this->debug('┕ Number of enriched messages to dispatch: ' . count($enrichedMessages));
49
        $this->indent++;
50
        foreach ($enrichedMessages as $enrichedMessage) {
51
            $this->dispatch($enrichedMessage);
52
        }
53
        $this->indent--;
54
        $this->indent--;
55
    }
56
57
    private function acceptsMessage(\ReflectionMethod $method, RawMessage $message) : bool
58
    {
59
        $parameters = $method->getParameters();
60
        foreach ($parameters as $parameter) {
61
            if ($parameter->getClass() && $parameter->getClass()->name === get_class($message)) {
62
                return true;
63
            }
64
        }
65
        return false;
66
    }
67
68
    /**
69
     * @param string $pluginClass
70
     * @return \ReflectionMethod[]
71
     */
72
    private function getPluginMethods(string $pluginClass) : array
73
    {
74
        return $this->removeUnsupportedMethods(
75
            (new \ReflectionClass($pluginClass))->getMethods()
76
        );
77
    }
78
79
    /**
80
     * @param \ReflectionMethod[] $methods
81
     * @return \ReflectionMethod[]
82
     */
83
    private function removeUnsupportedMethods(array $methods) : array
84
    {
85
        return array_filter($methods, function (\ReflectionMethod $method) {
86
            return $method->isPublic() && !$method->isStatic();
87
        });
88
    }
89
90
    private function debug(string $message)
91
    {
92
        $indention = str_repeat(' ', $this->indent*2);
93
        $this->core->make(Client::class)->logDebug($indention . $message);
94
    }
95
}
96