CommandExtractor::setDictionary()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Botonomous;
4
5
use Botonomous\utility\ArrayUtility;
6
use Botonomous\utility\MessageUtility;
7
use NlpTools\Stemmers\PorterStemmer;
8
use NlpTools\Tokenizers\WhitespaceAndPunctuationTokenizer;
9
10
/**
11
 * Class CommandExtractor.
12
 */
13
class CommandExtractor
14
{
15
    private $config;
16
    private $error;
17
    private $messageUtility;
18
    private $dictionary;
19
    private $commandContainer;
20
21
    /**
22
     * @param string $message
23
     *
24
     * @throws \Exception
25
     *
26
     * @return Command|null|void
27
     */
28 8
    public function getCommandByMessage(string $message)
29
    {
30 8
        if (empty($message)) {
31 1
            $this->setError('Message is empty');
32
33 1
            return;
34
        }
35
36
        /*
37
         * Process the message and find explicitly specified command
38
         */
39 7
        return $this->getCommandObjectByMessage($message);
40
    }
41
42
    /**
43
     * @param string $message
44
     *
45
     * @throws \Exception
46
     *
47
     * @return array
48
     */
49 4
    public function countKeywordOccurrence(string $message): array
50
    {
51 4
        $stemmer = new PorterStemmer();
52
53
        // tokenize $message
54 4
        $stemmed = implode(' ', $stemmer->stemAll((new WhitespaceAndPunctuationTokenizer())->tokenize($message)));
55
56 4
        $count = [];
57 4
        foreach ($this->getCommandContainer()->getAllAsObject() as $commandKey => $commandObject) {
58 4
            $keywordsCount = $this->commandKeywordOccurrence($commandObject, $stemmed);
59
60 4
            $total = 0;
61 4
            if (empty($keywordsCount)) {
62 4
                $count[$commandKey] = $total;
63 4
                continue;
64
            }
65
66 2
            $count[$commandKey] = array_sum($keywordsCount);
67
        }
68
69 4
        return $count;
70
    }
71
72
    /**
73
     * @param Command $command
74
     * @param string  $message
75
     *
76
     * @return array|void
77
     */
78 4
    private function commandKeywordOccurrence(Command $command, string $message)
79
    {
80 4
        $stemmer = new PorterStemmer();
81 4
        $keywords = $command->getKeywords();
82 4
        if (empty($keywords)) {
83 4
            return;
84
        }
85
86 4
        return $this->getMessageUtility()->keywordCount(
87 4
            $stemmer->stemAll($keywords),
88 4
            $message
89
        );
90
    }
91
92
    /**
93
     * @param string $message
94
     *
95
     * @throws \Exception
96
     *
97
     * @return Command|null
98
     */
99 7
    private function getCommandObjectByMessage(string $message)
100
    {
101 7
        $command = $this->getMessageUtility()->extractCommandName($message);
102 7
        if (empty($command)) {
103 3
            $command = (new ArrayUtility())->maxPositiveValueKey($this->countKeywordOccurrence($message));
104
        }
105
106
        // check command name
107 7
        if (empty($command)) {
108
            // get the default command if no command is find in the message
109 3
            $command = $this->checkDefaultCommand();
110
        }
111
112 7
        return $this->getCommandObjectByCommand($command);
113
    }
114
115
    /**
116
     * @throws \Exception
117
     *
118
     * @return mixed|void
119
     */
120 3
    private function checkDefaultCommand()
121
    {
122 3
        $command = $this->getConfig()->get('defaultCommand');
123
124 3
        if (empty($command)) {
125 2
            $this->setError($this->getDictionary()->get('generic-messages')['noCommandMessage']);
126
127 2
            return;
128
        }
129
130 1
        return $command;
131
    }
132
133
    /**
134
     * @param $command
135
     *
136
     * @throws \Exception
137
     *
138
     * @return Command|void
139
     */
140 7
    private function getCommandObjectByCommand($command)
141
    {
142 7
        if (empty($command)) {
143 2
            return;
144
        }
145
146 5
        $commandObject = $this->getCommandContainer()->getAsObject($command);
147
148 5
        if ($this->validateCommandObject($commandObject) !== true) {
149 2
            return;
150
        }
151
152 5
        return $commandObject;
153
    }
154
155
    /**
156
     * Validate the command object.
157
     *
158
     * @param Command|null $commandObject
159
     *
160
     * @throws \Exception
161
     *
162
     * @return bool
163
     */
164 5
    private function validateCommandObject($commandObject): bool
165
    {
166
        // check command details
167 5
        if (empty($commandObject)) {
168 2
            $this->setError(
169 2
                $this->getDictionary()->getValueByKey('generic-messages', 'unknownCommandMessage')
170
            );
171
172 2
            return false;
173
        }
174
175 5
        return true;
176
    }
177
178
    /**
179
     * @return string
180
     */
181 4
    public function getError(): string
182
    {
183 4
        return $this->error;
184
    }
185
186
    /**
187
     * @param string $error
188
     */
189 5
    public function setError(string $error)
190
    {
191 5
        $this->error = $error;
192 5
    }
193
194
    /**
195
     * @return Config
196
     */
197 4
    public function getConfig(): Config
198
    {
199 4
        if ($this->config === null) {
200 3
            $this->config = (new Config());
201
        }
202
203 4
        return $this->config;
204
    }
205
206
    /**
207
     * @param Config $config
208
     */
209 1
    public function setConfig(Config $config)
210
    {
211 1
        $this->config = $config;
212 1
    }
213
214
    /**
215
     * @return MessageUtility
216
     */
217 8
    public function getMessageUtility(): MessageUtility
218
    {
219 8
        if (!isset($this->messageUtility)) {
220 8
            $this->setMessageUtility(new MessageUtility());
221
        }
222
223 8
        return $this->messageUtility;
224
    }
225
226
    /**
227
     * @param MessageUtility $messageUtility
228
     */
229 8
    public function setMessageUtility(MessageUtility $messageUtility)
230
    {
231 8
        $this->messageUtility = $messageUtility;
232 8
    }
233
234
    /**
235
     * @return Dictionary
236
     */
237 4
    public function getDictionary(): Dictionary
238
    {
239 4
        if (!isset($this->dictionary)) {
240 4
            $this->setDictionary(new Dictionary());
241
        }
242
243 4
        return $this->dictionary;
244
    }
245
246
    /**
247
     * @param Dictionary $dictionary
248
     */
249 4
    public function setDictionary(Dictionary $dictionary)
250
    {
251 4
        $this->dictionary = $dictionary;
252 4
    }
253
254
    /**
255
     * @return CommandContainer
256
     */
257 8
    public function getCommandContainer(): CommandContainer
258
    {
259 8
        if (!isset($this->commandContainer)) {
260 6
            $this->setCommandContainer(new CommandContainer());
261
        }
262
263 8
        return $this->commandContainer;
264
    }
265
266
    /**
267
     * @param CommandContainer $commandContainer
268
     */
269 8
    public function setCommandContainer(CommandContainer $commandContainer)
270
    {
271 8
        $this->commandContainer = $commandContainer;
272 8
    }
273
}
274