Passed
Push — master ( 627c19...f3fe5e )
by Armando
03:09
created

Conversation::updateStatus()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3.0123

Importance

Changes 0
Metric Value
cc 3
eloc 10
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 16
ccs 8
cts 9
cp 0.8889
crap 3.0123
rs 9.9332
1
<?php
2
3
/**
4
 * This file is part of the TelegramBot package.
5
 *
6
 * (c) Avtandil Kikabidze aka LONGMAN <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Longman\TelegramBot;
13
14
use Longman\TelegramBot\Exception\TelegramException;
15
16
/**
17
 * Class Conversation
18
 *
19
 * Only one conversation can be active at any one time.
20
 * A conversation is directly linked to a user, chat and the command that is managing the conversation.
21
 */
22
class Conversation
23
{
24
    /**
25
     * All information fetched from the database
26
     *
27
     * @var array|null
28
     */
29
    protected $conversation;
30
31
    /**
32
     * Notes stored inside the conversation
33
     *
34
     * @var mixed
35
     */
36
    protected $protected_notes;
37
38
    /**
39
     * Notes to be stored
40
     *
41
     * @var mixed
42
     */
43
    public $notes;
44
45
    /**
46
     * Telegram user id
47
     *
48
     * @var int
49
     */
50
    protected $user_id;
51
52
    /**
53
     * Telegram chat id
54
     *
55
     * @var int
56
     */
57
    protected $chat_id;
58
59
    /**
60
     * Command to be executed if the conversation is active
61
     *
62
     * @var string
63
     */
64
    protected $command;
65
66
    /**
67
     * Conversation constructor to initialize a new conversation
68
     *
69
     * @param int    $user_id
70
     * @param int    $chat_id
71
     * @param string $command
72
     *
73
     * @throws TelegramException
74
     */
75 9
    public function __construct(int $user_id, int $chat_id, string $command = '')
76
    {
77 9
        $this->user_id = $user_id;
78 9
        $this->chat_id = $chat_id;
79 9
        $this->command = $command;
80
81
        //Try to load an existing conversation if possible
82 9
        if (!$this->load() && $command !== '') {
83
            //A new conversation start
84 6
            $this->start();
85
        }
86
    }
87
88
    /**
89
     * Clear all conversation variables.
90
     *
91
     * @return bool Always return true, to allow this method in an if statement.
92
     */
93 2
    protected function clear(): bool
94
    {
95 2
        $this->conversation    = null;
96 2
        $this->protected_notes = null;
97 2
        $this->notes           = null;
98
99 2
        return true;
100
    }
101
102
    /**
103
     * Load the conversation from the database
104
     *
105
     * @return bool
106
     * @throws TelegramException
107
     */
108 9
    protected function load(): bool
109
    {
110
        //Select an active conversation
111 9
        $conversation = ConversationDB::selectConversation($this->user_id, $this->chat_id, 1);
112 9
        if (isset($conversation[0])) {
113
            //Pick only the first element
114 5
            $this->conversation = $conversation[0];
115
116
            //Load the command from the conversation if it hasn't been passed
117 5
            $this->command = $this->command ?: $this->conversation['command'];
118
119 5
            if ($this->command !== $this->conversation['command']) {
120
                $this->cancel();
121
                return false;
122
            }
123
124
            //Load the conversation notes
125 5
            $this->protected_notes = json_decode($this->conversation['notes'], true);
126 5
            $this->notes           = $this->protected_notes;
127
        }
128
129 9
        return $this->exists();
130
    }
131
132
    /**
133
     * Check if the conversation already exists
134
     *
135
     * @return bool
136
     */
137 9
    public function exists(): bool
138
    {
139 9
        return $this->conversation !== null;
140
    }
141
142
    /**
143
     * Start a new conversation if the current command doesn't have one yet
144
     *
145
     * @return bool
146
     * @throws TelegramException
147
     */
148 6
    protected function start(): bool
149
    {
150
        if (
151 6
            $this->command
152 6
            && !$this->exists()
153 6
            && ConversationDB::insertConversation(
154 6
                $this->user_id,
155 6
                $this->chat_id,
156 6
                $this->command
157
            )
158
        ) {
159 5
            return $this->load();
160
        }
161
162
        return false;
163
    }
164
165
    /**
166
     * Delete the current conversation
167
     *
168
     * Currently the Conversation is not deleted but just set to 'stopped'
169
     *
170
     * @return bool
171
     * @throws TelegramException
172
     */
173 1
    public function stop(): bool
174
    {
175 1
        return $this->updateStatus('stopped') && $this->clear();
176
    }
177
178
    /**
179
     * Cancel the current conversation
180
     *
181
     * @return bool
182
     * @throws TelegramException
183
     */
184 1
    public function cancel(): bool
185
    {
186 1
        return $this->updateStatus('cancelled') && $this->clear();
187
    }
188
189
    /**
190
     * Update the status of the current conversation
191
     *
192
     * @param string $status
193
     *
194
     * @return bool
195
     * @throws TelegramException
196
     */
197 2
    protected function updateStatus(string $status): bool
198
    {
199 2
        if ($this->exists()) {
200 2
            $fields = ['status' => $status];
201
            $where  = [
202 2
                'id'      => $this->conversation['id'],
203
                'status'  => 'active',
204 2
                'user_id' => $this->user_id,
205 2
                'chat_id' => $this->chat_id,
206
            ];
207 2
            if (ConversationDB::updateConversation($fields, $where)) {
208 2
                return true;
209
            }
210
        }
211
212
        return false;
213
    }
214
215
    /**
216
     * Store the array/variable in the database with json_encode() function
217
     *
218
     * @return bool
219
     * @throws TelegramException
220
     */
221 1
    public function update(): bool
222
    {
223 1
        if ($this->exists()) {
224 1
            $fields = ['notes' => json_encode($this->notes, JSON_UNESCAPED_UNICODE)];
225
            //I can update a conversation whatever the state is
226 1
            $where = ['id' => $this->conversation['id']];
227 1
            if (ConversationDB::updateConversation($fields, $where)) {
228 1
                return true;
229
            }
230
        }
231
232
        return false;
233
    }
234
235
    /**
236
     * Retrieve the command to execute from the conversation
237
     *
238
     * @return string
239
     */
240 5
    public function getCommand(): string
241
    {
242 5
        return $this->command;
243
    }
244
245
    /**
246
     * Retrieve the user id
247
     *
248
     * @return int
249
     */
250 2
    public function getUserId(): int
251
    {
252 2
        return $this->user_id;
253
    }
254
255
    /**
256
     * Retrieve the chat id
257
     *
258
     * @return int
259
     */
260 2
    public function getChatId(): int
261
    {
262 2
        return $this->chat_id;
263
    }
264
}
265