Completed
Push — master ( 269bc3...61fa52 )
by Vladimir
36:35
created

Bot::clearContext()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 9.4285
cc 2
eloc 4
nc 2
nop 0
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace FondBot;
6
7
use FondBot\Channels\Channel;
8
use FondBot\Contracts\Drivers\User;
9
use FondBot\Contracts\Drivers\Driver;
10
use FondBot\Conversation\IntentManager;
11
use FondBot\Conversation\ContextManager;
12
use FondBot\Contracts\Bot as BotContract;
13
use FondBot\Contracts\Container\Container;
14
use FondBot\Contracts\Conversation\Intent;
15
use FondBot\Contracts\Conversation\Context;
16
use FondBot\Contracts\Conversation\Keyboard;
17
use FondBot\Contracts\Drivers\InvalidRequest;
18
use FondBot\Contracts\Drivers\OutgoingMessage;
19
use FondBot\Contracts\Conversation\Conversable;
20
use FondBot\Contracts\Conversation\Interaction;
21
use FondBot\Contracts\Drivers\Extensions\WebhookVerification;
22
23
class Bot implements BotContract
24
{
25
    /** @var Bot */
26
    protected static $instance;
27
28
    private $container;
29
    private $channel;
30
    private $driver;
31
32
    /** @var Context|null */
33
    private $context;
34
35 9
    protected function __construct(
36
        Container $container,
37
        Channel $channel,
38
        Driver $driver
39
    ) {
40 9
        $this->container = $container;
41 9
        $this->channel = $channel;
42 9
        $this->driver = $driver;
43 9
    }
44
45
    /**
46
     * Create new bot instance.
47
     *
48
     * @param Container $container
49
     * @param Channel   $channel
50
     * @param Driver    $driver
51
     * @param array     $request
52
     * @param array     $headers
53
     */
54 9
    public static function createInstance(
55
        Container $container,
56
        Channel $channel,
57
        Driver $driver,
58
        array $request,
59
        array $headers
60
    ): void {
61 9
        static::setInstance(
62 9
            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...
63
        );
64 9
    }
65
66
    /**
67
     * Get current instance.
68
     *
69
     * @return BotContract
70
     */
71 9
    public static function getInstance(): BotContract
72
    {
73 9
        return static::$instance;
74
    }
75
76
    /**
77
     * Set instance of the bot.
78
     *
79
     * @param Bot $instance
80
     */
81 58
    public static function setInstance(Bot $instance): void
82
    {
83 58
        static::$instance = $instance;
84 58
    }
85
86
    /**
87
     * Get context instance.
88
     *
89
     * @return Context|null
90
     */
91 2
    public function getContext(): ?Contracts\Conversation\Context
92
    {
93 2
        return $this->context;
94
    }
95
96
    /**
97
     * Set context instance.
98
     *
99
     * @param Context $context
100
     */
101 2
    public function setContext(Context $context): void
102
    {
103 2
        $this->context = $context;
104 2
    }
105
106
    /**
107
     * Clear context.
108
     */
109 1
    public function clearContext(): void
110
    {
111 1
        if ($this->context !== null) {
112 1
            $this->contextManager()->clear($this->context);
113 1
            $this->context = null;
114
        }
115 1
    }
116
117
    /**
118
     * Resolve from container.
119
     *
120
     * @param string $class
121
     *
122
     * @return mixed
123
     */
124 3
    public function get(string $class)
125
    {
126 3
        return $this->container->make($class);
127
    }
128
129
    /**
130
     * Process webhook request.
131
     *
132
     * @return mixed
133
     */
134 4
    public function process()
135
    {
136
        try {
137
            // Driver has webhook verification
138 4
            if ($this->driver instanceof WebhookVerification && $this->driver->isVerificationRequest()) {
139 1
                return $this->driver->verifyWebhook();
140
            }
141
142
            // Verify request
143 3
            $this->driver->verifyRequest();
144
145
            // Resolve context
146 2
            $this->context = $this->contextManager()->resolve($this->channel->getName(), $this->driver);
147
148 2
            if ($this->context->getInteraction() !== null) {
149 1
                $this->converse($this->context->getInteraction());
0 ignored issues
show
Documentation introduced by
$this->context->getInteraction() is of type object<FondBot\Contracts...nversation\Interaction>, but the function expects a object<FondBot\Contracts...nversation\Conversable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
150
            } else {
151 1
                $intent = $this->intentManager()->find($this->driver->getMessage());
152
153 1
                if ($intent !== null) {
154 1
                    $this->converse($intent);
0 ignored issues
show
Documentation introduced by
$intent is of type object<FondBot\Contracts\Conversation\Intent>, but the function expects a object<FondBot\Contracts...nversation\Conversable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
155
                }
156
            }
157
158 2
            if ($this->context !== null) {
159 2
                $this->contextManager()->save($this->context);
160
            }
161
162 2
            return 'OK';
163 1
        } catch (InvalidRequest $exception) {
164 1
            return $exception->getMessage();
165
        }
166
    }
167
168
    /**
169
     * Start conversation.
170
     *
171
     * @param Conversable|Intent|Interaction $conversable
172
     */
173 2
    public function converse(Conversable $conversable): void
174
    {
175 2
        if ($conversable instanceof Intent) {
176 1
            $this->context->setIntent($conversable);
177 1
            $this->context->setInteraction(null);
178 1
            $this->context->setValues([]);
179
180 1
            $conversable->handle($this);
181
        } elseif ($conversable instanceof Interaction) {
182 1
            $conversable->handle($this);
183
        }
184 2
    }
185
186
    /**
187
     * Send message.
188
     *
189
     * @param User          $recipient
190
     * @param string        $text
191
     * @param Keyboard|null $keyboard
192
     * @param string|null   $driver
193
     *
194
     * @return OutgoingMessage|null
195
     */
196 2
    public function sendMessage(
197
        User $recipient,
198
        string $text,
199
        Keyboard $keyboard = null,
200
        string $driver = null
201
    ): ?OutgoingMessage {
202 2
        if ($driver !== null && !$this->driver instanceof $driver) {
203 1
            return null;
204
        }
205
206 1
        return $this->driver->sendMessage(
207
            $recipient,
208
            $text,
209
            $keyboard
210
        );
211
    }
212
213
    /**
214
     * Get context manager.
215
     *
216
     * @return ContextManager
217
     */
218 3
    private function contextManager(): ContextManager
219
    {
220 3
        return $this->get(ContextManager::class);
221
    }
222
223
    /**
224
     * Get intent manager.
225
     *
226
     * @return IntentManager
227
     */
228 1
    private function intentManager(): IntentManager
229
    {
230 1
        return $this->get(IntentManager::class);
231
    }
232
}
233