Completed
Push — master ( 87ab33...75849f )
by Ehsan
03:23
created

MessageUtility::keywordPos()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 18
ccs 9
cts 9
cp 1
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 9
nc 5
nop 2
crap 5
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 2
            return $found;
139
        }
140
141 3
        foreach ((new ArrayUtility())->sortArrayByLength($keywords) as $keyword) {
142 3
            foreach ((new StringUtility())->findPositionInString($keyword, $message) as $position) {
143
                // check if the keyword does not overlap with one of the already found
144 3
                if ($this->isPositionTaken($found, $position) === false) {
145 3
                    $found[$keyword][] = $position;
146
                }
147
            }
148
        }
149
150 3
        return $found;
151
    }
152
153 2
    public function keywordCount(array $keywords, $message)
154
    {
155 2
        $keysPositions = $this->keywordPos($keywords, $message);
156
157 2
        if (empty($keysPositions)) {
158 1
            return;
159
        }
160
161 2
        foreach ($keysPositions as $key => $positions) {
162 2
            $keysPositions[$key] = count($positions);
163
        }
164
165 2
        return $keysPositions;
166
    }
167
168
    /**
169
     * @param array $tokensPositions
170
     * @param       $newPosition
171
     *
172
     * @return bool
173
     */
174 3
    private function isPositionTaken(array $tokensPositions, $newPosition)
175
    {
176 3
        if (empty($tokensPositions)) {
177 3
            return false;
178
        }
179
180 3
        foreach ($tokensPositions as $token => $positions) {
181 3
            $tokenLength = strlen($token);
182 3
            if ($this->isPositionIn($newPosition, $positions, $tokenLength) === true) {
183 3
                return true;
184
            }
185
        }
186
187 3
        return false;
188
    }
189
190
    /**
191
     * @param $newPosition
192
     * @param $positions
193
     * @param $tokenLength
194
     *
195
     * @return bool
196
     */
197 3
    private function isPositionIn($newPosition, array $positions, $tokenLength)
198
    {
199 3
        foreach ($positions as $position) {
200 3
            if ($newPosition >= $position && $newPosition < $position + $tokenLength) {
201 3
                return true;
202
            }
203
        }
204
205 3
        return false;
206
    }
207
}
208