Completed
Push — master ( 1b605f...95b7c3 )
by Dan
06:00
created

PluginManager::loadPlugin()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 2
1
<?php
2
3
namespace Nopolabs\Yabot\Plugin;
4
5
6
use Exception;
7
use Nopolabs\Yabot\Helpers\LogTrait;
8
use Nopolabs\Yabot\Message\Message;
9
use Nopolabs\Yabot\Yabot;
10
use Psr\Log\LoggerInterface;
11
12
class PluginManager
13
{
14
    use LogTrait;
15
16
    const NO_PREFIX = '<none>';
17
18
    /** @var array */
19
    private $plugins;
20
21
    /** @var array */
22
    private $prefixMap;
23
24
    public function __construct(LoggerInterface $logger)
25
    {
26
        $this->setLog($logger);
27
28
        $this->plugins = [];
29
        $this->prefixMap = [];
30
    }
31
32
    public function getPrefixMap() : array
33
    {
34
        return $this->prefixMap;
35
    }
36
37
    public function loadPlugin($pluginId, PluginInterface $plugin)
38
    {
39
        if (isset($this->plugins[$pluginId])) {
40
            $this->warning("$pluginId already loaded, ignoring duplicate.");
41
            return;
42
        }
43
44
        $this->addPlugin($pluginId, $plugin);
45
46
        $this->info('loaded', ['pluginId' => $pluginId, 'prefix' => $plugin->getPrefix()]);
47
    }
48
49
    public function getHelp() : array
50
    {
51
        $help = [];
52
        foreach ($this->getPrefixMap() as $prefix => $plugins) {
53
            /** @var PluginInterface $plugin */
54
            foreach ($plugins as $pluginId => $plugin) {
55
                $help[] = $pluginId;
56
                foreach (explode("\n", $plugin->help()) as $line) {
57
                    if ($prefix === self::NO_PREFIX) {
58
                        $line = str_replace('<prefix> ', '', $line);
59
                    } else {
60
                        $line = str_replace('<prefix>', $prefix, $line);
61
                    }
62
                    $help[] = '    ' . $line;
63
                }
64
            }
65
        }
66
67
        return $help;
68
    }
69
70
    public function getStatuses() : array
71
    {
72
        $count = count($this->plugins);
73
74
        $statuses = [];
75
        $statuses[] = "There are $count plugins loaded.";
76
        foreach ($this->getPrefixMap() as $prefix => $plugins) {
77
            /** @var PluginInterface $plugin */
78
            foreach ($plugins as $pluginId => $plugin) {
79
                $statuses[] = "$pluginId " . $plugin->status();
80
            }
81
        }
82
83
        return $statuses;
84
    }
85
86
    public function dispatchMessage(Message $message)
87
    {
88
        $text = $message->getFormattedText();
89
90
        $this->info('dispatchMessage: ', ['formattedText' => $text]);
91
92
        foreach ($this->getPrefixMap() as $prefix => $plugins) {
93
94
            if (!($matches = $this->matchesPrefix($prefix, $text))) {
95
                continue;
96
            }
97
98
            $this->debug('Matched prefix', ['prefix' => $prefix]);
99
100
            $text = ltrim($matches[1]);
101
102
            $message->setPluginText($text);
103
104 View Code Duplication
            foreach ($plugins as $pluginId => $plugin) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across 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...
105
                /** @var PluginInterface $plugin */
106
                try {
107
                    $plugin->handle($message);
108
                } catch (Exception $e) {
109
                    $this->warning("Unhandled Exception in $pluginId: ".$e->getMessage());
110
                    $this->warning($e->getTraceAsString());
111
                }
112
113
                if ($message->isHandled()) {
114
                    return;
115
                }
116
            }
117
118
            if ($message->isHandled()) {
119
                return;
120
            }
121
        }
122
    }
123
124
    public function updatePrefixes($authedUsername)
125
    {
126
        $updated = [];
127
128
        foreach ($this->getPrefixMap() as $prefix => $plugins) {
129
            if ($prefix === Yabot::AUTHED_USER) {
130
                $prefix = '@' . $authedUsername;
131
            } elseif (!$prefix) {
132
                $prefix = self::NO_PREFIX;
133
            }
134
135
            $updated[$prefix] = $plugins;
136
        }
137
138
        $this->prefixMap = $updated;
139
    }
140
141
    public function matchesPrefix($prefix, $text) : array
142
    {
143
        if ($prefix === self::NO_PREFIX) {
144
            return [$text, $text];
145
        }
146
147
        preg_match("/^$prefix\\s+(.*)/", $text, $matches);
148
149
        return $matches;
150
    }
151
152
    protected function addPlugin($pluginId, PluginInterface $plugin)
153
    {
154
        $this->plugins[$pluginId] = $plugin;
155
156
        $prefix = $plugin->getPrefix();
157
158
        if (!isset($this->prefixMap[$prefix])) {
159
            $this->prefixMap[$prefix] = [];
160
        }
161
162
        $this->prefixMap[$prefix][$pluginId] = $plugin;
163
    }
164
}