Completed
Push — master ( 1fad07...9ffd04 )
by Vladimir
08:28
created

Kernel::driverManager()   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 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace FondBot\Application;
6
7
use FondBot\Drivers\Driver;
8
use FondBot\Channels\Channel;
9
use League\Container\Container;
10
use FondBot\Conversation\Intent;
11
use FondBot\Conversation\Context;
12
use FondBot\Drivers\DriverManager;
13
use FondBot\Conversation\Conversable;
14
use FondBot\Conversation\Interaction;
15
use FondBot\Conversation\IntentManager;
16
use FondBot\Conversation\ContextManager;
17
use Psr\Http\Message\ServerRequestInterface;
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 Context|null */
31
    private $context;
32
33 6
    public function __construct(Container $container)
34
    {
35 6
        $this->container = $container;
36 6
    }
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 context instance.
64
     *
65
     * @return Context|null
66
     */
67 2
    public function getContext(): ?Context
68
    {
69 2
        return $this->context;
70
    }
71
72
    /**
73
     * Set context instance.
74
     *
75
     * @param Context $context
76
     */
77 2
    public function setContext(Context $context): void
78
    {
79 2
        $this->context = $context;
80 2
    }
81
82
    /**
83
     * Clear context.
84
     *
85
     * @throws \Psr\Container\ContainerExceptionInterface
86
     */
87 1
    public function clearContext(): void
88
    {
89 1
        if ($this->context !== null) {
90 1
            $this->contextManager()->clear($this->context);
91 1
            $this->context = 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 5
    public function resolve(string $class)
104
    {
105 5
        return $this->container->get($class);
106
    }
107
108
    /**
109
     * Process webhook request.
110
     *
111
     * @param Channel                $channel
112
     * @param ServerRequestInterface $request
113
     *
114
     * @return mixed
115
     *
116
     * @throws \Psr\Container\ContainerExceptionInterface
117
     * @throws \FondBot\Drivers\Exceptions\DriverNotFound
118
     */
119 4
    public function process(Channel $channel, ServerRequestInterface $request)
120
    {
121
        try {
122 4
            $driver = $this->driverManager()->get($channel, $request);
123
124 4
            $this->container->add('channel', $channel);
125 4
            $this->container->add('driver', $driver);
126
127
            // Driver has webhook verification
128 4
            if ($driver instanceof WebhookVerification && $driver->isVerificationRequest()) {
129 1
                return $driver->verifyWebhook();
130
            }
131
132
            // Verify request
133 3
            $driver->verifyRequest();
134
135
            // Resolve context
136 2
            $this->context = $this->contextManager()->resolve($channel->getName(), $driver);
137
138 2
            if ($this->context->getInteraction() !== null) {
139 1
                $this->converse($this->context->getInteraction());
140
            } else {
141 1
                $intent = $this->intentManager()->find($driver->getMessage());
142
143 1
                if ($intent !== null) {
144 1
                    $this->converse($intent);
145
                }
146
            }
147
148 2
            if ($this->context !== null) {
149 2
                $this->contextManager()->save($this->context);
150
            }
151
152 2
            return 'OK';
153 1
        } catch (InvalidRequest $exception) {
154 1
            return $exception->getMessage();
155
        }
156
    }
157
158
    /**
159
     * Start conversation.
160
     *
161
     * @param Conversable $conversable
162
     */
163 2
    public function converse(Conversable $conversable): void
164
    {
165 2
        if ($conversable instanceof Intent) {
166 1
            $this->context->setIntent($conversable);
167 1
            $this->context->setInteraction(null);
168 1
            $this->context->setValues([]);
169
170 1
            $conversable->handle($this);
171
        } elseif ($conversable instanceof Interaction) {
172 1
            $conversable->handle($this);
173
        }
174 2
    }
175
176
    /**
177
     * Get driver manager.
178
     *
179
     * @return DriverManager
180
     *
181
     * @throws \Psr\Container\ContainerExceptionInterface
182
     */
183 4
    private function driverManager(): DriverManager
184
    {
185 4
        return $this->resolve(DriverManager::class);
186
    }
187
188
    /**
189
     * Get context manager.
190
     *
191
     * @return ContextManager
192
     *
193
     * @throws \Psr\Container\ContainerExceptionInterface
194
     */
195 3
    private function contextManager(): ContextManager
196
    {
197 3
        return $this->resolve(ContextManager::class);
198
    }
199
200
    /**
201
     * Get intent manager.
202
     *
203
     * @return IntentManager
204
     *
205
     * @throws \Psr\Container\ContainerExceptionInterface
206
     */
207 1
    private function intentManager(): IntentManager
208
    {
209 1
        return $this->resolve(IntentManager::class);
210
    }
211
}
212