Completed
Push — master ( 17cc82...87aff1 )
by Vladimir
04:11
created

Bot   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 193
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 9

Test Coverage

Coverage 98.25%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 22
c 1
b 0
f 0
lcom 2
cbo 9
dl 0
loc 193
ccs 56
cts 57
cp 0.9825
rs 10

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A createInstance() 0 11 1
A getInstance() 0 4 1
A setInstance() 0 4 1
A getContext() 0 4 1
A setContext() 0 4 1
A clearContext() 0 7 2
A get() 0 4 1
C process() 0 33 7
A converse() 0 12 3
A sendMessage() 0 4 1
A contextManager() 0 4 1
A intentManager() 0 4 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace FondBot;
6
7
use FondBot\Drivers\OutgoingMessage;
8
use FondBot\Drivers\Driver;
9
use FondBot\Channels\Channel;
10
use FondBot\Contracts\Container;
11
use FondBot\Conversation\Intent;
12
use FondBot\Conversation\Context;
13
use FondBot\Conversation\Conversable;
14
use FondBot\Conversation\Interaction;
15
use FondBot\Conversation\IntentManager;
16
use FondBot\Conversation\ContextManager;
17
use FondBot\Drivers\Exceptions\InvalidRequest;
18
use FondBot\Drivers\Extensions\WebhookVerification;
19
20
class Bot
21
{
22
    /** @var Bot */
23
    protected static $instance;
24
25
    private $container;
26
    private $channel;
27
    private $driver;
28
29
    /** @var Context|null */
30
    private $context;
31
32 8
    protected function __construct(
33
        Container $container,
34
        Channel $channel,
35
        Driver $driver
36
    ) {
37 8
        $this->container = $container;
38 8
        $this->channel = $channel;
39 8
        $this->driver = $driver;
40 8
    }
41
42
    /**
43
     * Create new bot instance.
44
     *
45
     * @param Container $container
46
     * @param Channel   $channel
47
     * @param Driver    $driver
48
     * @param array     $request
49
     * @param array     $headers
50
     */
51 8
    public static function createInstance(
52
        Container $container,
53
        Channel $channel,
54
        Driver $driver,
55
        array $request,
56
        array $headers
57
    ): void {
58 8
        static::setInstance(
59 8
            new static($container, $channel, $driver, $request, $headers)
0 ignored issues
show
Unused Code introduced by
The call to Bot::__construct() has too many arguments starting with $request.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
60
        );
61 8
    }
62
63
    /**
64
     * Get current instance.
65
     *
66
     * @return Bot
67
     */
68 8
    public static function getInstance(): Bot
69
    {
70 8
        return static::$instance;
71
    }
72
73
    /**
74
     * Set instance of the bot.
75
     *
76
     * @param Bot $instance
77
     */
78 56
    public static function setInstance(Bot $instance): void
79
    {
80 56
        static::$instance = $instance;
81 56
    }
82
83
    /**
84
     * Get context instance.
85
     *
86
     * @return Context|null
87
     */
88 2
    public function getContext(): ?Context
89
    {
90 2
        return $this->context;
91
    }
92
93
    /**
94
     * Set context instance.
95
     *
96
     * @param Context $context
97
     */
98 2
    public function setContext(Context $context): void
99
    {
100 2
        $this->context = $context;
101 2
    }
102
103
    /**
104
     * Clear context.
105
     */
106 1
    public function clearContext(): void
107
    {
108 1
        if ($this->context !== null) {
109 1
            $this->contextManager()->clear($this->context);
110 1
            $this->context = null;
111
        }
112 1
    }
113
114
    /**
115
     * Resolve from container.
116
     *
117
     * @param string $class
118
     *
119
     * @return mixed
120
     */
121 3
    public function get(string $class)
122
    {
123 3
        return $this->container->make($class);
124
    }
125
126
    /**
127
     * Process webhook request.
128
     *
129
     * @return mixed
130
     */
131 4
    public function process()
132
    {
133
        try {
134
            // Driver has webhook verification
135 4
            if ($this->driver instanceof WebhookVerification && $this->driver->isVerificationRequest()) {
136 1
                return $this->driver->verifyWebhook();
137
            }
138
139
            // Verify request
140 3
            $this->driver->verifyRequest();
141
142
            // Resolve context
143 2
            $this->context = $this->contextManager()->resolve($this->channel->getName(), $this->driver);
144
145 2
            if ($this->context->getInteraction() !== null) {
146 1
                $this->converse($this->context->getInteraction());
147
            } else {
148 1
                $intent = $this->intentManager()->find($this->driver->getMessage());
149
150 1
                if ($intent !== null) {
151 1
                    $this->converse($intent);
152
                }
153
            }
154
155 2
            if ($this->context !== null) {
156 2
                $this->contextManager()->save($this->context);
157
            }
158
159 2
            return 'OK';
160 1
        } catch (InvalidRequest $exception) {
161 1
            return $exception->getMessage();
162
        }
163
    }
164
165
    /**
166
     * Start conversation.
167
     *
168
     * @param Conversable $conversable
169
     */
170 2
    public function converse(Conversable $conversable): void
171
    {
172 2
        if ($conversable instanceof Intent) {
173 1
            $this->context->setIntent($conversable);
174 1
            $this->context->setInteraction(null);
175 1
            $this->context->setValues([]);
176
177 1
            $conversable->handle($this);
178
        } elseif ($conversable instanceof Interaction) {
179 1
            $conversable->handle($this);
180
        }
181 2
    }
182
183
    /**
184
     * Send message.
185
     *
186
     * @param OutgoingMessage $message
187
     */
188 1
    public function sendMessage(OutgoingMessage $message): void
189
    {
190 1
        $this->driver->sendMessage($message);
191 1
    }
192
193
    /**
194
     * Get context manager.
195
     *
196
     * @return ContextManager
197
     */
198 3
    private function contextManager(): ContextManager
199
    {
200 3
        return $this->get(ContextManager::class);
201
    }
202
203
    /**
204
     * Get intent manager.
205
     *
206
     * @return IntentManager
207
     */
208 1
    private function intentManager(): IntentManager
209
    {
210 1
        return $this->get(IntentManager::class);
211
    }
212
}
213