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

PluginManager   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 153
Duplicated Lines 8.5 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 27
lcom 1
cbo 3
dl 13
loc 153
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A getPrefixMap() 0 4 1
A loadPlugin() 0 11 2
B getHelp() 0 20 5
A getStatuses() 0 15 3
C dispatchMessage() 13 37 7
A updatePrefixes() 0 16 4
A matchesPrefix() 0 10 2
A addPlugin() 0 12 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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
}