Completed
Push — 1.0 ( dd1957...1757a3 )
by Vladimir
02:38
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 FondBot\Conversation\Intent;
10
use FondBot\Conversation\Context;
11
use FondBot\Drivers\DriverManager;
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
26
    /** @var Context|null */
27
    private $context;
28
29 6
    public function __construct(Container $container)
30
    {
31 6
        $this->container = $container;
32 6
    }
33
34
    /**
35
     * Get current driver instance.
36
     *
37
     * @return Driver
38
     */
39 1
    public function getDriver(): Driver
40
    {
41 1
        return $this->container->get('driver');
42
    }
43
44
    /**
45
     * Get context instance.
46
     *
47
     * @return Context|null
48
     */
49 2
    public function getContext(): ?Context
50
    {
51 2
        return $this->context;
52
    }
53
54
    /**
55
     * Set context instance.
56
     *
57
     * @param Context $context
58
     */
59 2
    public function setContext(Context $context): void
60
    {
61 2
        $this->context = $context;
62 2
    }
63
64
    /**
65
     * Clear context.
66
     */
67 1
    public function clearContext(): void
68
    {
69 1
        if ($this->context !== null) {
70 1
            $this->contextManager()->clear($this->context);
71 1
            $this->context = null;
72
        }
73 1
    }
74
75
    /**
76
     * Resolve from container.
77
     *
78
     * @param string $class
79
     *
80
     * @return mixed
81
     */
82 5
    public function resolve(string $class)
83
    {
84 5
        return $this->container->get($class);
85
    }
86
87
    /**
88
     * Process webhook request.
89
     *
90
     * @param Channel $channel
91
     *
92
     * @param array   $request
93
     * @param array   $headers
94
     *
95
     * @return mixed
96
     */
97 4
    public function process(Channel $channel, array $request, array $headers)
98
    {
99
        try {
100 4
            $driver = $this->driverManager()->get($channel);
101
102 4
            $this->container->add('driver', $driver);
103
104 4
            $driver->fill($channel->getParameters(), $request, $headers);
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