Completed
Push — master ( 3af321...67fa71 )
by Ehsan
02:53
created

MessageUtility   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 202
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 4

Test Coverage

Coverage 96.61%

Importance

Changes 0
Metric Value
wmc 27
c 0
b 0
f 0
lcom 2
cbo 4
dl 0
loc 202
ccs 57
cts 59
cp 0.9661
rs 10

11 Methods

Rating   Name   Duplication   Size   Complexity  
A removeMentionedBot() 0 6 1
A isBotMentioned() 0 6 1
A extractCommandName() 0 18 2
A extractCommandDetails() 0 8 1
A removeTriggerWord() 0 6 1
A linkToUser() 0 12 3
A getUserLink() 0 4 1
C keywordPos() 0 26 7
A keywordCount() 0 14 3
B isPositionTaken() 0 17 5
A isPositionIn() 0 4 2
1
<?php
2
3
namespace Botonomous\utility;
4
5
use Botonomous\CommandContainer;
6
7
/**
8
 * Class MessageUtility.
9
 */
10
class MessageUtility extends AbstractUtility
11
{
12
    /**
13
     * Remove the mentioned bot username from the message.
14
     *
15
     * @param $message
16
     *
17
     * @throws \Exception
18
     *
19
     * @return string
20
     */
21 9
    public function removeMentionedBot($message)
22
    {
23 9
        $userLink = $this->getUserLink();
24
25 9
        return preg_replace("/{$userLink}/", '', $message, 1);
26
    }
27
28
    /**
29
     * Check if the bot user id is mentioned in the message.
30
     *
31
     * @param $message
32
     *
33
     * @throws \Exception
34
     *
35
     * @return bool
36
     */
37 2
    public function isBotMentioned($message)
38
    {
39 2
        $userLink = $this->getUserLink();
40
41 2
        return (new StringUtility())->findInString($userLink, $message, false);
42
    }
43
44
    /**
45
     * Return command name in the message.
46
     *
47
     * @param $message
48
     *
49
     * @return null|string
50
     */
51 8
    public function extractCommandName($message)
52
    {
53
        // remove the bot mention if it exists
54 8
        $message = $this->removeMentionedBot($message);
55
56
        /**
57
         * Command must start with / and at the beginning of the sentence.
58
         */
59 8
        $commandPrefix = $this->getConfig()->get('commandPrefix');
60 8
        $commandPrefix = preg_quote($commandPrefix, '/');
61
62 8
        $pattern = '/^('.$commandPrefix.'\w{1,})/';
63
64 8
        preg_match($pattern, ltrim($message), $groups);
65
66
        // If command is found, remove command prefix from the beginning of the command
67 8
        return isset($groups[1]) ? ltrim($groups[1], $commandPrefix) : null;
68
    }
69
70
    /**
71
     * Return command details in the message.
72
     *
73
     * @param $message
74
     *
75
     * @return \Botonomous\Command|null
76
     */
77 1
    public function extractCommandDetails($message)
78
    {
79
        // first get the command name
80 1
        $command = $this->extractCommandName($message);
81
82
        // then get the command details
83 1
        return (new CommandContainer())->getAsObject($command);
84
    }
85
86
    /**
87
     * @param $triggerWord
88
     * @param $message
89
     *
90
     * @return string
91
     */
92 4
    public function removeTriggerWord($message, $triggerWord)
93
    {
94 4
        $count = 1;
95
96 4
        return ltrim(str_replace($triggerWord, '', $message, $count));
97
    }
98
99
    /**
100
     * @param        $userId
101
     * @param string $userName
102
     *
103
     * @throws \Exception
104
     *
105
     * @return string
106
     */
107 12
    public function linkToUser($userId, $userName = '')
108
    {
109 12
        if (empty($userId)) {
110 1
            throw new \Exception('User id is not provided');
111
        }
112
113 12
        if (!empty($userName)) {
114 1
            $userName = "|{$userName}";
115
        }
116
117 12
        return "<@{$userId}{$userName}>";
118
    }
119
120
    /**
121
     * @return string
122
     */
123 11
    private function getUserLink()
124
    {
125 11
        return $this->linkToUser($this->getConfig()->get('botUserId'));
126
    }
127
128
    /**
129
     * @param array $keywords
130
     * @param       $message
131
     *
132
     * @return array
133
     */
134 3
    public function keywordPos(array $keywords, $message)
135
    {
136 3
        $found = [];
137 3
        if (empty($keywords)) {
138
            return $found;
139
        }
140
141 3
        usort($keywords, function ($array1, $array2) {
142 3
            return strlen($array2) <=> strlen($array1);
143 3
        });
144
145 3
        foreach ($keywords as $keyword) {
146 3
            $result = preg_match_all("/\b{$keyword}\b/", $message, $matches, PREG_OFFSET_CAPTURE);
147
148 3
            if ($result && !empty($matches[0])) {
149 3
                foreach ($matches[0] as $match) {
150
                    // check if the keyword does not overlap with one of the already found
151 3
                    if ($this->isPositionTaken($found, $match[1]) === false) {
152 3
                        $found[$keyword][] = $match[1];
153
                    }
154
                }
155
            }
156
        }
157
158 3
        return $found;
159
    }
160
161 2
    public function keywordCount(array $keywords, $message)
162
    {
163 2
        $keysPositions = $this->keywordPos($keywords, $message);
164
165 2
        if (empty($keysPositions)) {
166
            return;
167
        }
168
169 2
        foreach ($keysPositions as $key => $positions) {
170 2
            $keysPositions[$key] = count($positions);
171
        }
172
173 2
        return $keysPositions;
174
    }
175
176
    /**
177
     * @param array $tokensPositions
178
     * @param       $newPosition
179
     *
180
     * @return bool
181
     */
182 3
    private function isPositionTaken(array $tokensPositions, $newPosition)
183
    {
184 3
        if (empty($tokensPositions)) {
185 3
            return false;
186
        }
187
188 3
        foreach ($tokensPositions as $token => $positions) {
189 3
            $tokenLength = strlen($token);
190 3
            foreach ($positions as $position) {
191 3
                if ($this->isPositionIn($newPosition, $position, $tokenLength) === true) {
192 3
                    return true;
193
                }
194
            }
195
        }
196
197 3
        return false;
198
    }
199
200
    /**
201
     * @param $newPosition
202
     * @param $position
203
     * @param $tokenLength
204
     *
205
     * @return bool
206
     */
207 3
    private function isPositionIn($newPosition, $position, $tokenLength)
208
    {
209 3
        return $newPosition >= $position && $newPosition < $position + $tokenLength;
210
    }
211
}
212