Completed
Push — master ( f31b80...e72317 )
by Vladimir
03:02
created

Bot::sendAttachment()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 2
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace FondBot;
6
7
use FondBot\Drivers\User;
8
use FondBot\Drivers\Driver;
9
use FondBot\Channels\Channel;
10
use FondBot\Contracts\Container;
11
use FondBot\Conversation\Intent;
12
use FondBot\Conversation\Context;
13
use FondBot\Conversation\Keyboard;
14
use FondBot\Drivers\OutgoingMessage;
15
use FondBot\Conversation\Conversable;
16
use FondBot\Conversation\Interaction;
17
use FondBot\Conversation\IntentManager;
18
use FondBot\Conversation\ContextManager;
19
use FondBot\Drivers\Exceptions\InvalidRequest;
20
use FondBot\Drivers\ReceivedMessage\Attachment;
21
use FondBot\Drivers\Extensions\WebhookVerification;
22
23
class Bot
24
{
25
    /** @var Bot */
26
    protected static $instance;
27
28
    private $container;
29
    private $channel;
30
    private $driver;
31
32
    /** @var Context|null */
33
    private $context;
34
35 10
    protected function __construct(
36
        Container $container,
37
        Channel $channel,
38
        Driver $driver
39
    ) {
40 10
        $this->container = $container;
41 10
        $this->channel = $channel;
42 10
        $this->driver = $driver;
43 10
    }
44
45
    /**
46
     * Create new bot instance.
47
     *
48
     * @param Container $container
49
     * @param Channel   $channel
50
     * @param Driver    $driver
51
     */
52 10
    public static function createInstance(
53
        Container $container,
54
        Channel $channel,
55
        Driver $driver
56
    ): void {
57 10
        static::setInstance(
58 10
            new static($container, $channel, $driver)
59
        );
60 10
    }
61
62
    /**
63
     * Get current instance.
64
     *
65
     * @return Bot
66
     */
67 10
    public static function getInstance(): Bot
68
    {
69 10
        return static::$instance;
70
    }
71
72
    /**
73
     * Set instance of the bot.
74
     *
75
     * @param Bot $instance
76
     */
77 81
    public static function setInstance(Bot $instance): void
78
    {
79 81
        static::$instance = $instance;
80 81
    }
81
82
    /**
83
     * Get context instance.
84
     *
85
     * @return Context|null
86
     */
87 2
    public function getContext(): ?Context
88
    {
89 2
        return $this->context;
90
    }
91
92
    /**
93
     * Set context instance.
94
     *
95
     * @param Context $context
96
     */
97 2
    public function setContext(Context $context): void
98
    {
99 2
        $this->context = $context;
100 2
    }
101
102
    /**
103
     * Clear context.
104
     */
105 1
    public function clearContext(): void
106
    {
107 1
        if ($this->context !== null) {
108 1
            $this->contextManager()->clear($this->context);
109 1
            $this->context = null;
110
        }
111 1
    }
112
113
    /**
114
     * Resolve from container.
115
     *
116
     * @param string $class
117
     *
118
     * @return mixed
119
     */
120 3
    public function get(string $class)
121
    {
122 3
        return $this->container->make($class);
123
    }
124
125
    /**
126
     * Process webhook request.
127
     *
128
     * @return mixed
129
     */
130 4
    public function process()
131
    {
132
        try {
133
            // Driver has webhook verification
134 4
            if ($this->driver instanceof WebhookVerification && $this->driver->isVerificationRequest()) {
135 1
                return $this->driver->verifyWebhook();
136
            }
137
138
            // Verify request
139 3
            $this->driver->verifyRequest();
140
141
            // Resolve context
142 2
            $this->context = $this->contextManager()->resolve($this->channel->getName(), $this->driver);
143
144 2
            if ($this->context->getInteraction() !== null) {
145 1
                $this->converse($this->context->getInteraction());
146
            } else {
147 1
                $intent = $this->intentManager()->find($this->driver->getMessage());
148
149 1
                if ($intent !== null) {
150 1
                    $this->converse($intent);
151
                }
152
            }
153
154 2
            if ($this->context !== null) {
155 2
                $this->contextManager()->save($this->context);
156
            }
157
158 2
            return 'OK';
159 1
        } catch (InvalidRequest $exception) {
160 1
            return $exception->getMessage();
161
        }
162
    }
163
164
    /**
165
     * Start conversation.
166
     *
167
     * @param Conversable $conversable
168
     */
169 2
    public function converse(Conversable $conversable): void
170
    {
171 2
        if ($conversable instanceof Intent) {
172 1
            $this->context->setIntent($conversable);
173 1
            $this->context->setInteraction(null);
174 1
            $this->context->setValues([]);
175
176 1
            $conversable->handle($this);
177
        } elseif ($conversable instanceof Interaction) {
178 1
            $conversable->handle($this);
179
        }
180 2
    }
181
182
    /**
183
     * Send message.
184
     *
185
     * @param User          $recipient
186
     * @param string        $text
187
     * @param Keyboard|null $keyboard
188
     * @param string|null   $driver
189
     *
190
     * @return OutgoingMessage|null
191
     */
192 2
    public function sendMessage(
193
        User $recipient,
194
        string $text,
195
        Keyboard $keyboard = null,
196
        string $driver = null
197
    ): ?OutgoingMessage {
198 2
        if ($driver !== null && !$this->driver instanceof $driver) {
199 1
            return null;
200
        }
201
202 1
        return $this->driver->sendMessage(
203
            $recipient,
204
            $text,
205
            $keyboard
206
        );
207
    }
208
209
    /**
210
     * Send attachment.
211
     *
212
     * @param User       $recipient
213
     * @param Attachment $attachment
214
     */
215 1
    public function sendAttachment(User $recipient, Attachment $attachment): void
216
    {
217 1
        $this->driver->sendAttachment($recipient, $attachment);
218 1
    }
219
220
    /**
221
     * Get context manager.
222
     *
223
     * @return ContextManager
224
     */
225 3
    private function contextManager(): ContextManager
226
    {
227 3
        return $this->get(ContextManager::class);
228
    }
229
230
    /**
231
     * Get intent manager.
232
     *
233
     * @return IntentManager
234
     */
235 1
    private function intentManager(): IntentManager
236
    {
237 1
        return $this->get(IntentManager::class);
238
    }
239
}
240