Completed
Push — master ( 030b5f...d05431 )
by Vladimir
02:51
created

Kernel::resolve()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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