Completed
Push — master ( f3e44e...1f022d )
by Vladimir
02:48
created

ConversationManager::restart()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
nc 4
nop 1
dl 0
loc 12
ccs 0
cts 7
cp 0
crap 12
rs 9.8666
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A ConversationManager::getCacheKeyForContext() 0 4 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace FondBot\Conversation;
6
7
use FondBot\Channels\Chat;
8
use FondBot\Channels\User;
9
use FondBot\Channels\Channel;
10
use Illuminate\Cache\Repository;
11
use FondBot\Events\MessageReceived;
12
use FondBot\Contracts\Conversation\Manager;
13
use FondBot\Contracts\Conversation\Conversable;
14
use Illuminate\Contracts\Foundation\Application;
15
16
class ConversationManager implements Manager
17
{
18
    private $intents = [];
19
    private $fallbackIntent;
20
21
    private $application;
22
    private $cache;
23
24
    private $transitioned = false;
25
26
    private $messageReceived;
27
28 81
    public function __construct(Application $application, Repository $cache)
29
    {
30 81
        $this->application = $application;
31 81
        $this->cache = $cache;
32 81
    }
33
34
    /** {@inheritdoc} */
35 2
    public function registerIntent(string $class): void
36
    {
37 2
        $this->intents[] = $class;
38 2
    }
39
40
    /** {@inheritdoc} */
41 81
    public function registerFallbackIntent(string $class): void
42
    {
43 81
        $this->fallbackIntent = $class;
44 81
    }
45
46
    /** {@inheritdoc} */
47 1
    public function getIntents(): array
48
    {
49 1
        return $this->intents;
50
    }
51
52
    /** {@inheritdoc} */
53 1
    public function matchIntent(MessageReceived $messageReceived): ?Intent
54
    {
55 1
        foreach ($this->intents as $intent) {
56
            /** @var Intent $intent */
57 1
            $intent = resolve($intent);
0 ignored issues
show
Documentation introduced by
$intent is of type object<FondBot\Conversation\Intent>, but the function expects a string.

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...
58
59 1
            foreach ($intent->activators() as $activator) {
60 1
                if ($activator->matches($messageReceived) && $intent->passesAuthorization($messageReceived)) {
61 1
                    return $intent;
62
                }
63
            }
64
        }
65
66
        // Otherwise, return fallback intent
67 1
        return resolve($this->fallbackIntent);
68
    }
69
70
    /** {@inheritdoc} */
71 1
    public function resolveContext(Channel $channel, Chat $chat, User $user): Context
72
    {
73 1
        $value = $this->cache->get($this->getCacheKeyForContext($channel, $chat, $user), [
74 1
            'chat' => $chat,
75 1
            'user' => $user,
76
            'intent' => null,
77
            'interaction' => null,
78
            'items' => [],
79
        ]);
80
81 1
        $context = new Context($channel, $chat, $user, $value['items'] ?? []);
82
83 1
        if (isset($value['intent'])) {
84 1
            $context->setIntent(resolve($value['intent']));
85
        }
86
87 1
        if (isset($value['interaction'])) {
88 1
            $context->setInteraction(resolve($value['interaction']));
89
        }
90
91
        // Bind resolved instance to the container
92 1
        $this->application->instance('fondbot.conversation.context', $context);
93
94 1
        return $context;
95
    }
96
97
    /** {@inheritdoc} */
98 1
    public function saveContext(Context $context): void
99
    {
100 1
        $this->cache->forever(
101 1
            $this->getCacheKeyForContext($context->getChannel(), $context->getChat(), $context->getUser()),
102 1
            $context->toArray()
103
        );
104 1
    }
105
106
    /** {@inheritdoc} */
107
    public function flushContext(Context $context): void
108
    {
109
        $this->cache->forget(
110
            $this->getCacheKeyForContext($context->getChannel(), $context->getChat(), $context->getUser())
111
        );
112
    }
113
114
    /** {@inheritdoc} */
115 81
    public function getContext(): ?Context
116
    {
117 81
        if (!$this->application->has('fondbot.conversation.context')) {
118 81
            return null;
119
        }
120
121 14
        return $this->application->get('fondbot.conversation.context');
122
    }
123
124
    /** {@inheritdoc} */
125
    public function setReceivedMessage(MessageReceived $messageReceived): void
126
    {
127
        $this->messageReceived = $messageReceived;
128
    }
129
130
    /** {@inheritdoc} */
131
    public function markAsTransitioned(): void
132
    {
133
        $this->transitioned = true;
134
    }
135
136
    /** {@inheritdoc} */
137
    public function transitioned(): bool
138
    {
139
        return $this->transitioned;
140
    }
141
142
    /** {@inheritdoc} */
143
    public function converse(Conversable $conversable): void
144
    {
145
        context()->incrementAttempts();
146
147
        if ($conversable instanceof Intent) {
148
            context()->setIntent($conversable)->setInteraction(null);
149
        }
150
151
        $conversable->handle($this->messageReceived);
152
    }
153
154 81
    public function __destruct()
155
    {
156 81
        $context = $this->getContext();
157
158 81
        if ($context === null) {
159 81
            return;
160
        }
161
162
        // Close session if conversation has not been transitioned
163
        if (!$this->transitioned()) {
164
            $this->flushContext($context);
165
        }
166
167
        // Save context if exists
168
        if ($this->transitioned() && $context = context()) {
169
            $this->saveContext($context);
170
        }
171
    }
172
173 2
    private function getCacheKeyForContext(Channel $channel, Chat $chat, User $user): string
174
    {
175 2
        return implode('.', ['context', $channel->getName(), $chat->getId(), $user->getId()]);
176
    }
177
}
178