Passed
Branch 1.0 (f7255b)
by Vladimir
06:00
created

Kernel   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 189
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 9

Test Coverage

Coverage 98.21%

Importance

Changes 0
Metric Value
wmc 22
lcom 2
cbo 9
dl 0
loc 189
ccs 55
cts 56
cp 0.9821
rs 10
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A createInstance() 0 9 1
A getInstance() 0 4 1
A setInstance() 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 33 7
A converse() 0 12 3
A contextManager() 0 4 1
A intentManager() 0 4 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 FondBot\Contracts\Container;
10
use FondBot\Conversation\Intent;
11
use FondBot\Conversation\Context;
12
use FondBot\Conversation\Conversable;
13
use FondBot\Conversation\Interaction;
14
use FondBot\Conversation\IntentManager;
15
use FondBot\Conversation\ContextManager;
16
use FondBot\Drivers\Exceptions\InvalidRequest;
17
use FondBot\Drivers\Extensions\WebhookVerification;
18
19
class Kernel
20
{
21
    /** @var Kernel */
22
    protected static $instance;
23
24
    private $container;
25
    private $channel;
26
    private $driver;
27
28
    /** @var Context|null */
29
    private $context;
30
31 7
    protected function __construct(
32
        Container $container,
33
        Channel $channel,
34
        Driver $driver
35
    ) {
36 7
        $this->container = $container;
37 7
        $this->channel = $channel;
38 7
        $this->driver = $driver;
39 7
    }
40
41
    /**
42
     * Create new kernel instance.
43
     *
44
     * @param Container $container
45
     * @param Channel   $channel
46
     * @param Driver    $driver
47
     */
48 7
    public static function createInstance(
49
        Container $container,
50
        Channel $channel,
51
        Driver $driver
52
    ): void {
53 7
        static::setInstance(
54 7
            new static($container, $channel, $driver)
55
        );
56 7
    }
57
58
    /**
59
     * Get current instance.
60
     *
61
     * @return Kernel
62
     */
63 7
    public static function getInstance(): Kernel
64
    {
65 7
        return static::$instance;
66
    }
67
68
    /**
69
     * Set kernel instance.
70
     *
71
     * @param Kernel $instance
72
     */
73 93
    public static function setInstance(Kernel $instance): void
74
    {
75 93
        static::$instance = $instance;
76 93
    }
77
78
    /**
79
     * Get current driver instance.
80
     *
81
     * @return Driver
82
     */
83 1
    public function getDriver(): Driver
84
    {
85 1
        return $this->driver;
86
    }
87
88
    /**
89
     * Get context instance.
90
     *
91
     * @return Context|null
92
     */
93 2
    public function getContext(): ?Context
94
    {
95 2
        return $this->context;
96
    }
97
98
    /**
99
     * Set context instance.
100
     *
101
     * @param Context $context
102
     */
103 2
    public function setContext(Context $context): void
104
    {
105 2
        $this->context = $context;
106 2
    }
107
108
    /**
109
     * Clear context.
110
     */
111 1
    public function clearContext(): void
112
    {
113 1
        if ($this->context !== null) {
114 1
            $this->contextManager()->clear($this->context);
115 1
            $this->context = null;
116
        }
117 1
    }
118
119
    /**
120
     * Resolve from container.
121
     *
122
     * @param string $class
123
     *
124
     * @return mixed
125
     */
126 3
    public function resolve(string $class)
127
    {
128 3
        return $this->container->make($class);
129
    }
130
131
    /**
132
     * Process webhook request.
133
     *
134
     * @return mixed
135
     */
136 4
    public function process()
137
    {
138
        try {
139
            // Driver has webhook verification
140 4
            if ($this->driver instanceof WebhookVerification && $this->driver->isVerificationRequest()) {
141 1
                return $this->driver->verifyWebhook();
142
            }
143
144
            // Verify request
145 3
            $this->driver->verifyRequest();
146
147
            // Resolve context
148 2
            $this->context = $this->contextManager()->resolve($this->channel->getName(), $this->driver);
149
150 2
            if ($this->context->getInteraction() !== null) {
151 1
                $this->converse($this->context->getInteraction());
152
            } else {
153 1
                $intent = $this->intentManager()->find($this->driver->getMessage());
154
155 1
                if ($intent !== null) {
156 1
                    $this->converse($intent);
157
                }
158
            }
159
160 2
            if ($this->context !== null) {
161 2
                $this->contextManager()->save($this->context);
162
            }
163
164 2
            return 'OK';
165 1
        } catch (InvalidRequest $exception) {
166 1
            return $exception->getMessage();
167
        }
168
    }
169
170
    /**
171
     * Start conversation.
172
     *
173
     * @param Conversable $conversable
174
     */
175 2
    public function converse(Conversable $conversable): void
176
    {
177 2
        if ($conversable instanceof Intent) {
178 1
            $this->context->setIntent($conversable);
179 1
            $this->context->setInteraction(null);
180 1
            $this->context->setValues([]);
181
182 1
            $conversable->handle($this);
183
        } elseif ($conversable instanceof Interaction) {
184 1
            $conversable->handle($this);
185
        }
186 2
    }
187
188
    /**
189
     * Get context manager.
190
     *
191
     * @return ContextManager
192
     */
193 3
    private function contextManager(): ContextManager
194
    {
195 3
        return $this->resolve(ContextManager::class);
196
    }
197
198
    /**
199
     * Get intent manager.
200
     *
201
     * @return IntentManager
202
     */
203 1
    private function intentManager(): IntentManager
204
    {
205 1
        return $this->resolve(IntentManager::class);
206
    }
207
}
208