Passed
Branch 1.0 (690a53)
by Vladimir
07:08
created

Kernel   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 164
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Test Coverage

Coverage 97.96%

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 10
dl 0
loc 164
ccs 48
cts 49
cp 0.9796
rs 10
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A converse() 0 12 3
A driverManager() 0 4 1
A contextManager() 0 4 1
A intentManager() 0 4 1
A __construct() 0 4 1
A getDriver() 0 4 1
A getContext() 0 4 1
A setContext() 0 4 1
A clearContext() 0 7 2
A resolve() 0 4 1
C process() 0 37 7
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 driver instance.
40
     *
41
     * @return Driver
42
     */
43 1
    public function getDriver(): Driver
44
    {
45 1
        return $this->container->get('driver');
46
    }
47
48
    /**
49
     * Get context instance.
50
     *
51
     * @return Context|null
52
     */
53 2
    public function getContext(): ?Context
54
    {
55 2
        return $this->context;
56
    }
57
58
    /**
59
     * Set context instance.
60
     *
61
     * @param Context $context
62
     */
63 2
    public function setContext(Context $context): void
64
    {
65 2
        $this->context = $context;
66 2
    }
67
68
    /**
69
     * Clear context.
70
     */
71 1
    public function clearContext(): void
72
    {
73 1
        if ($this->context !== null) {
74 1
            $this->contextManager()->clear($this->context);
75 1
            $this->context = null;
76
        }
77 1
    }
78
79
    /**
80
     * Resolve from container.
81
     *
82
     * @param string $class
83
     *
84
     * @return mixed
85
     */
86 5
    public function resolve(string $class)
87
    {
88 5
        return $this->container->get($class);
89
    }
90
91
    /**
92
     * Process webhook request.
93
     *
94
     * @param Channel                $channel
95
     * @param ServerRequestInterface $request
96
     *
97
     * @return mixed
98
     */
99 4
    public function process(Channel $channel, ServerRequestInterface $request)
100
    {
101
        try {
102 4
            $driver = $this->driverManager()->get($channel, $request);
103
104 4
            $this->container->add('driver', $driver);
105
106
            // Driver has webhook verification
107 4
            if ($driver instanceof WebhookVerification && $driver->isVerificationRequest()) {
108 1
                return $driver->verifyWebhook();
109
            }
110
111
            // Verify request
112 3
            $driver->verifyRequest();
113
114
            // Resolve context
115 2
            $this->context = $this->contextManager()->resolve($channel->getName(), $driver);
116
117 2
            if ($this->context->getInteraction() !== null) {
118 1
                $this->converse($this->context->getInteraction());
119
            } else {
120 1
                $intent = $this->intentManager()->find($driver->getMessage());
121
122 1
                if ($intent !== null) {
123 1
                    $this->converse($intent);
124
                }
125
            }
126
127 2
            if ($this->context !== null) {
128 2
                $this->contextManager()->save($this->context);
129
            }
130
131 2
            return 'OK';
132 1
        } catch (InvalidRequest $exception) {
133 1
            return $exception->getMessage();
134
        }
135
    }
136
137
    /**
138
     * Start conversation.
139
     *
140
     * @param Conversable $conversable
141
     */
142 2
    public function converse(Conversable $conversable): void
143
    {
144 2
        if ($conversable instanceof Intent) {
145 1
            $this->context->setIntent($conversable);
146 1
            $this->context->setInteraction(null);
147 1
            $this->context->setValues([]);
148
149 1
            $conversable->handle($this);
150
        } elseif ($conversable instanceof Interaction) {
151 1
            $conversable->handle($this);
152
        }
153 2
    }
154
155
    /**
156
     * Get driver manager.
157
     *
158
     * @return DriverManager
159
     */
160 4
    private function driverManager(): DriverManager
161
    {
162 4
        return $this->resolve(DriverManager::class);
163
    }
164
165
    /**
166
     * Get context manager.
167
     *
168
     * @return ContextManager
169
     */
170 3
    private function contextManager(): ContextManager
171
    {
172 3
        return $this->resolve(ContextManager::class);
173
    }
174
175
    /**
176
     * Get intent manager.
177
     *
178
     * @return IntentManager
179
     */
180 1
    private function intentManager(): IntentManager
181
    {
182 1
        return $this->resolve(IntentManager::class);
183
    }
184
}
185