Completed
Push — master ( 3147c9...abfbd6 )
by Vladimir
03:05
created

ConversationManager::flushContext()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 6
ccs 0
cts 4
cp 0
crap 2
rs 9.4285
c 0
b 0
f 0
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 Illuminate\Contracts\Foundation\Application;
14
15
class ConversationManager implements Manager
16
{
17
    private $intents = [];
18
    private $fallbackIntent;
19
20
    private $application;
21
    private $cache;
22
23
    private $transitioned = false;
24
25 72
    public function __construct(Application $application, Repository $cache)
26
    {
27 72
        $this->application = $application;
28 72
        $this->cache = $cache;
29 72
    }
30
31
    /**
32
     * Register intent.
33
     *
34
     * @param string $class
35
     */
36
    public function registerIntent(string $class): void
37
    {
38
        $this->intents[] = $class;
39
    }
40
41
    /**
42
     * Register fallback intent.
43
     *
44
     * @param string $class
45
     */
46 72
    public function registerFallbackIntent(string $class): void
47
    {
48 72
        $this->fallbackIntent = $class;
49 72
    }
50
51
    /**
52
     * Get all registered intents.
53
     *
54
     * @return array
55
     */
56
    public function getIntents(): array
57
    {
58
        return $this->intents;
59
    }
60
61
    /**
62
     * Match intent by received message.
63
     *
64
     * @param MessageReceived $messageReceived
65
     *
66
     * @return Intent|null
67
     */
68
    public function matchIntent(MessageReceived $messageReceived): ?Intent
69
    {
70
        foreach ($this->intents as $intent) {
71
            /** @var Intent $intent */
72
            $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...
73
74
            foreach ($intent->activators() as $activator) {
75
                if ($activator->matches($messageReceived) && $intent->passesAuthorization($messageReceived)) {
76
                    return $intent;
77
                }
78
            }
79
        }
80
81
        // Otherwise, return fallback intent
82
        return resolve($this->fallbackIntent);
83
    }
84
85
    /**
86
     * Resolve conversation context.
87
     *
88
     * @param Channel $channel
89
     * @param Chat    $chat
90
     * @param User    $user
91
     *
92
     * @return Context|null
93
     */
94
    public function resolveContext(Channel $channel, Chat $chat, User $user): Context
95
    {
96
        $value = $this->cache->get($this->getCacheKeyForContext($channel, $chat, $user), [
97
            'chat' => $chat,
98
            'user' => $user,
99
            'intent' => null,
100
            'interaction' => null,
101
        ]);
102
103
        $context = new Context($channel, $chat, $user);
104
105
        if ($value['intent'] !== null) {
106
            $context->setIntent($value['intent']);
107
        }
108
109
        if ($value['interaction'] !== null) {
110
            $context->setInteraction($value['interaction']);
111
        }
112
113
        // Bind resolved instance to the container
114
        $this->application->instance('fondbot.conversation.context', $context);
115
116
        return $context;
117
    }
118
119
    /**
120
     * Save context.
121
     *
122
     * @param Context $context
123
     */
124
    public function saveContext(Context $context): void
125
    {
126
        $this->cache->forever(
127
            $this->getCacheKeyForContext($context->getChannel(), $context->getChat(), $context->getUser()),
128
            $context->toArray()
129
        );
130
    }
131
132
    /**
133
     * Flush context.
134
     *
135
     * @param Context $context
136
     */
137
    public function flushContext(Context $context): void
138
    {
139
        $this->cache->forget(
140
            $this->getCacheKeyForContext($context->getChannel(), $context->getChat(), $context->getUser())
141
        );
142
    }
143
144
    /**
145
     * Get current context.
146
     *
147
     * @return Context|null
148
     */
149 72
    public function getContext(): ?Context
150
    {
151 72
        if (!$this->application->has('fondbot.conversation.context')) {
152 72
            return null;
153
        }
154
155 14
        return $this->application->get('fondbot.conversation.context');
156
    }
157
158
    /**
159
     * Mark conversation as transitioned.
160
     */
161
    public function markAsTransitioned(): void
162
    {
163
        $this->transitioned = true;
164
    }
165
166
    /**
167
     * Determine if conversation has been transitioned.
168
     *
169
     * @return bool
170
     */
171
    public function transitioned(): bool
172
    {
173
        return $this->transitioned;
174
    }
175
176 72
    public function __destruct()
177
    {
178 72
        $context = $this->getContext();
179
180 72
        if ($context === null) {
181 72
            return;
182
        }
183
184
        // Close session if conversation has not been transitioned
185
        if (!$this->transitioned()) {
186
            $this->flushContext($context);
187
        }
188
189
        // Save context if exists
190
        if ($context = context()) {
191
            $this->saveContext($context);
192
        }
193
    }
194
195
    private function getCacheKeyForContext(Channel $channel, Chat $chat, User $user): string
196
    {
197
        return implode('.', ['context', $channel->getName(), $chat->getId(), $user->getId()]);
198
    }
199
}
200