Passed
Push — 1.0 ( 12d132...dd1957 )
by Vladimir
06:10
created

Kernel::setInstance()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

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