Passed
Push — master ( 4d23aa...6a3888 )
by Ehsan
03:02
created

CommandExtractor::getCommandObjectByMessage()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

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