FakeDriver   A
last analyzed

Complexity

Total Complexity 26

Size/Duplication

Total Lines 231
Duplicated Lines 0 %

Coupling/Cohesion

Components 6
Dependencies 5

Importance

Changes 0
Metric Value
wmc 26
lcom 6
cbo 5
dl 0
loc 231
rs 10
c 0
b 0
f 0

23 Methods

Rating   Name   Duplication   Size   Complexity  
A create() 0 4 1
A createInactive() 0 7 1
A matchesRequest() 0 4 1
A getMessages() 0 8 2
A isBot() 0 4 1
A isConfigured() 0 4 1
A setUser() 0 8 1
A getUser() 0 4 1
A getConversationAnswer() 0 7 1
A buildServicePayload() 0 4 1
A sendPayload() 0 7 2
A setName() 0 4 1
A getName() 0 4 1
A types() 0 4 1
A typesAndWaits() 0 4 1
A isBotTyping() 0 4 1
A setEventName() 0 4 1
A setEventPayload() 0 4 1
A hasMatchingEvent() 0 11 2
A getBotMessages() 0 4 1
A resetBotMessages() 0 5 1
A serializesCallbacks() 0 4 1
A verifyRequest() 0 6 1
1
<?php
2
3
namespace BotMan\BotMan\Drivers\Tests;
4
5
use BotMan\BotMan\Users\User;
6
use BotMan\BotMan\Messages\Incoming\Answer;
7
use BotMan\BotMan\Interfaces\DriverInterface;
8
use BotMan\BotMan\Interfaces\VerifiesService;
9
use BotMan\BotMan\Messages\Outgoing\Question;
10
use Symfony\Component\HttpFoundation\Request;
11
use BotMan\BotMan\Drivers\Events\GenericEvent;
12
use Symfony\Component\HttpFoundation\Response;
13
use BotMan\BotMan\Messages\Incoming\IncomingMessage;
14
15
/**
16
 * A fake driver for tests. Must be used with ProxyDriver.
17
 * Example to set it up in a unit test:
18
 * <code>
19
 *  public static function setUpBeforeClass()
20
 *  {
21
 *      DriverManager::loadDriver(ProxyDriver::class);
22
 *  }
23
 *  public function setUp()
24
 *  {
25
 *      $this->fakeDriver = new FakeDriver();
26
 *      ProxyDriver::setInstance($this->fakeDriver);
27
 *  }
28
 * </code>.
29
 */
30
class FakeDriver implements DriverInterface, VerifiesService
31
{
32
    /** @var bool */
33
    public $matchesRequest = true;
34
35
    /** @var bool */
36
    public $hasMatchingEvent = false;
37
38
    /** @var \BotMan\BotMan\Messages\Incoming\IncomingMessage[] */
39
    public $messages = [];
40
41
    /** @var bool */
42
    public $isBot = false;
43
44
    /** @var bool */
45
    public $isInteractiveMessageReply = false;
46
47
    /** @var bool */
48
    public $isConfigured = true;
49
50
    /** @var array */
51
    private $botMessages = [];
52
53
    /** @var bool */
54
    private $botIsTyping = false;
55
56
    /** @var string */
57
    private $driver_name = 'Fake';
58
59
    /** @var string */
60
    private $event_name;
61
62
    /** @var array */
63
    private $event_payload;
64
65
    /** @var string */
66
    private $user_id = null;
67
68
    /** @var string */
69
    private $user_first_name = 'Marcel';
70
71
    /** @var string */
72
    private $user_last_name = 'Pociot';
73
74
    /** @var string */
75
    private $username = 'BotMan';
76
77
    /** @var array */
78
    private $user_info = [];
79
80
    /**
81
     * @return FakeDriver
82
     */
83
    public static function create()
84
    {
85
        return new static;
86
    }
87
88
    /**
89
     * @return FakeDriver
90
     */
91
    public static function createInactive()
92
    {
93
        $driver = new static;
94
        $driver->isConfigured = false;
95
96
        return $driver;
97
    }
98
99
    public function matchesRequest()
100
    {
101
        return $this->matchesRequest;
102
    }
103
104
    public function getMessages()
105
    {
106
        foreach ($this->messages as &$message) {
107
            $message->setIsFromBot($this->isBot());
108
        }
109
110
        return $this->messages;
111
    }
112
113
    protected function isBot()
114
    {
115
        return $this->isBot;
116
    }
117
118
    public function isConfigured()
119
    {
120
        return $this->isConfigured;
121
    }
122
123
    public function setUser(array $user_info)
124
    {
125
        $this->user_id = $user_info['id'] ?? $this->user_id;
126
        $this->user_first_name = $user_info['first_name'] ?? $this->user_first_name;
127
        $this->user_last_name = $user_info['last_name'] ?? $this->user_last_name;
128
        $this->username = $user_info['username'] ?? $this->username;
129
        $this->user_info = $user_info;
130
    }
131
132
    public function getUser(IncomingMessage $matchingMessage)
133
    {
134
        return new User($this->user_id ?? $matchingMessage->getSender(), $this->user_first_name, $this->user_last_name, $this->username, $this->user_info);
135
    }
136
137
    public function getConversationAnswer(IncomingMessage $message)
138
    {
139
        $answer = Answer::create($message->getText())->setMessage($message)->setValue($message->getText());
140
        $answer->setInteractiveReply($this->isInteractiveMessageReply);
141
142
        return $answer;
143
    }
144
145
    public function buildServicePayload($message, $matchingMessage, $additionalParameters = [])
146
    {
147
        return $message;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $message; (string|BotMan\BotMan\Messages\Outgoing\Question) is incompatible with the return type declared by the interface BotMan\BotMan\Interfaces...ce::buildServicePayload of type BotMan\BotMan\Interfaces\DriverInterface.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
148
    }
149
150
    public function sendPayload($payload)
151
    {
152
        $this->botMessages[] = $payload;
153
        $text = method_exists($payload, 'getText') ? $payload->getText() : '';
154
155
        return Response::create(json_encode($text));
156
    }
157
158
    public function setName($name)
159
    {
160
        $this->driver_name = $name;
161
    }
162
163
    public function getName()
164
    {
165
        return $this->driver_name;
166
    }
167
168
    public function types(IncomingMessage $matchingMessage)
169
    {
170
        $this->botIsTyping = true;
171
    }
172
173
    /**
174
     * Send a typing indicator and wait for the given amount of seconds.
175
     * @param IncomingMessage $matchingMessage
176
     * @param float $seconds
177
     * @return mixed
178
     */
179
    public function typesAndWaits(IncomingMessage $matchingMessage, float $seconds)
180
    {
181
        $this->types($matchingMessage);
182
    }
183
184
    /**
185
     * Returns true if types() has been called.
186
     *
187
     * @return bool
188
     */
189
    public function isBotTyping()
190
    {
191
        return $this->botIsTyping;
192
    }
193
194
    /**
195
     * @return void
196
     */
197
    public function setEventName($name)
198
    {
199
        $this->event_name = $name;
200
    }
201
202
    /**
203
     * @return void
204
     */
205
    public function setEventPayload($payload)
206
    {
207
        $this->event_payload = $payload;
208
    }
209
210
    /**
211
     * @return bool|GenericEvent
212
     */
213
    public function hasMatchingEvent()
214
    {
215
        if (isset($this->event_name)) {
216
            $event = new GenericEvent($this->event_payload);
217
            $event->setName($this->event_name);
218
219
            return $event;
220
        }
221
222
        return $this->hasMatchingEvent;
223
    }
224
225
    /**
226
     * Returns array of messages from bot.
227
     *
228
     * @return string[]|Question[]
229
     */
230
    public function getBotMessages()
231
    {
232
        return $this->botMessages;
233
    }
234
235
    /**
236
     * Clear received messages from bot.
237
     */
238
    public function resetBotMessages()
239
    {
240
        $this->botIsTyping = false;
241
        $this->botMessages = [];
242
    }
243
244
    /**
245
     * Tells if the stored conversation callbacks are serialized.
246
     *
247
     * @return bool
248
     */
249
    public function serializesCallbacks()
250
    {
251
        return true;
252
    }
253
254
    public function verifyRequest(Request $request)
255
    {
256
        $_SERVER['driver_verified'] = true;
257
258
        return true;
259
    }
260
}
261