1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace NotificationChannels\Facebook; |
4
|
|
|
|
5
|
|
|
use JsonSerializable; |
6
|
|
|
use NotificationChannels\Facebook\Traits\HasButtons; |
7
|
|
|
use NotificationChannels\Facebook\Exceptions\CouldNotCreateMessage; |
8
|
|
|
use NotificationChannels\Facebook\Enums\{MessagingType, RecipientType, AttachmentType, NotificationType}; |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* Class FacebookMessage. |
12
|
|
|
*/ |
13
|
|
|
class FacebookMessage implements JsonSerializable |
14
|
|
|
{ |
15
|
|
|
use HasButtons; |
16
|
|
|
|
17
|
|
|
/** @var string Recipient's ID. */ |
18
|
|
|
public $recipient; |
19
|
|
|
|
20
|
|
|
/** @var string Recipient Type */ |
21
|
|
|
public $recipientType = RecipientType::ID; |
22
|
|
|
|
23
|
|
|
/** @var string Notification Text. */ |
24
|
|
|
public $text; |
25
|
|
|
|
26
|
|
|
/** @var string Notification Type */ |
27
|
|
|
public $notificationType = NotificationType::REGULAR; |
28
|
|
|
|
29
|
|
|
/** @var string Messaging Type. Defaults to UPDATE */ |
30
|
|
|
protected $messagingType = MessagingType::UPDATE; |
31
|
|
|
|
32
|
|
|
/** @var array Generic Template Cards (items) */ |
33
|
|
|
public $cards = []; |
34
|
|
|
|
35
|
|
|
/** @var string Attachment Type. Defaults to File */ |
36
|
|
|
public $attachmentType = AttachmentType::FILE; |
37
|
|
|
|
38
|
|
|
/** @var string Attachment URL */ |
39
|
|
|
public $attachmentUrl; |
40
|
|
|
|
41
|
|
|
/** @var bool */ |
42
|
|
|
protected $hasAttachment = false; |
43
|
|
|
|
44
|
|
|
/** @var bool */ |
45
|
|
|
protected $hasText = false; |
46
|
|
|
|
47
|
|
|
/** @var string Message tag used with messaging type MESSAGE_TAG */ |
48
|
|
|
protected $messageTag; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @param string $text |
52
|
|
|
* |
53
|
|
|
* @throws CouldNotCreateMessage |
54
|
|
|
* @return static |
55
|
|
|
*/ |
56
|
|
|
public static function create(string $text = ''): FacebookMessage |
57
|
|
|
{ |
58
|
|
|
return new static($text); |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* @param string $text |
63
|
|
|
* |
64
|
|
|
* @throws CouldNotCreateMessage |
65
|
|
|
*/ |
66
|
|
|
public function __construct(string $text = '') |
67
|
|
|
{ |
68
|
|
|
if ($text !== '') { |
69
|
|
|
$this->text($text); |
70
|
|
|
} |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* Recipient's PSID or Phone Number. |
75
|
|
|
* |
76
|
|
|
* The id must be an ID that was retrieved through the |
77
|
|
|
* Messenger entry points or through the Messenger webhooks. |
78
|
|
|
* |
79
|
|
|
* @param string|array $recipient ID of recipient or Phone number of the recipient with the format |
80
|
|
|
* +1(212)555-2368 |
81
|
|
|
* @param string $type Recipient Type: id, user_ref, phone_number, post_id, comment_id. |
82
|
|
|
* |
83
|
|
|
* @return $this |
84
|
|
|
*/ |
85
|
|
|
public function to($recipient, string $type = RecipientType::ID): self |
86
|
|
|
{ |
87
|
|
|
if (is_array($recipient)) { |
88
|
|
|
[$type, $recipient] = $recipient; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
$this->recipient = $recipient; |
|
|
|
|
92
|
|
|
$this->recipientType = $type; |
93
|
|
|
|
94
|
|
|
return $this; |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* Notification text. |
99
|
|
|
* |
100
|
|
|
* @param string $text |
101
|
|
|
* |
102
|
|
|
* @throws CouldNotCreateMessage |
103
|
|
|
* |
104
|
|
|
* @return $this |
105
|
|
|
*/ |
106
|
|
|
public function text(string $text): self |
107
|
|
|
{ |
108
|
|
|
if (mb_strlen($text) > 320) { |
109
|
|
|
throw CouldNotCreateMessage::textTooLong(); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
$this->text = $text; |
113
|
|
|
$this->hasText = true; |
114
|
|
|
|
115
|
|
|
return $this; |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* Add Attachment. |
120
|
|
|
* |
121
|
|
|
* @param string $attachmentType |
122
|
|
|
* @param string $url |
123
|
|
|
* |
124
|
|
|
* @throws CouldNotCreateMessage |
125
|
|
|
* |
126
|
|
|
* @return $this |
127
|
|
|
*/ |
128
|
|
|
public function attach(string $attachmentType, string $url): self |
129
|
|
|
{ |
130
|
|
|
$attachmentTypes = [ |
131
|
|
|
AttachmentType::FILE, |
132
|
|
|
AttachmentType::IMAGE, |
133
|
|
|
AttachmentType::VIDEO, |
134
|
|
|
AttachmentType::AUDIO, |
135
|
|
|
]; |
136
|
|
|
|
137
|
|
|
if (!in_array($attachmentType, $attachmentTypes, false)) { |
138
|
|
|
throw CouldNotCreateMessage::invalidAttachmentType(); |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
if (blank($url)) { |
142
|
|
|
throw CouldNotCreateMessage::urlNotProvided(); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
$this->attachmentType = $attachmentType; |
146
|
|
|
$this->attachmentUrl = $url; |
147
|
|
|
$this->hasAttachment = true; |
148
|
|
|
|
149
|
|
|
return $this; |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* Push notification type. |
154
|
|
|
* |
155
|
|
|
* @param string $notificationType Possible values: REGULAR, SILENT_PUSH, NO_PUSH |
156
|
|
|
* |
157
|
|
|
* @throws CouldNotCreateMessage |
158
|
|
|
* @return $this |
159
|
|
|
*/ |
160
|
|
|
public function notificationType(string $notificationType): self |
161
|
|
|
{ |
162
|
|
|
$notificationTypes = [ |
163
|
|
|
NotificationType::REGULAR, |
164
|
|
|
NotificationType::SILENT_PUSH, |
165
|
|
|
NotificationType::NO_PUSH, |
166
|
|
|
]; |
167
|
|
|
|
168
|
|
|
if (!in_array($notificationType, $notificationTypes, false)) { |
169
|
|
|
throw CouldNotCreateMessage::invalidNotificationType(); |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
$this->notificationType = $notificationType; |
173
|
|
|
|
174
|
|
|
return $this; |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* Helper to set notification type as REGULAR. |
179
|
|
|
* |
180
|
|
|
* @return $this |
181
|
|
|
*/ |
182
|
|
|
public function isTypeRegular(): self |
183
|
|
|
{ |
184
|
|
|
$this->notificationType = NotificationType::REGULAR; |
185
|
|
|
|
186
|
|
|
return $this; |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* Helper to set notification type as SILENT_PUSH. |
191
|
|
|
* |
192
|
|
|
* @return $this |
193
|
|
|
*/ |
194
|
|
|
public function isTypeSilentPush(): self |
195
|
|
|
{ |
196
|
|
|
$this->notificationType = NotificationType::SILENT_PUSH; |
197
|
|
|
|
198
|
|
|
return $this; |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
/** |
202
|
|
|
* Helper to set notification type as NO_PUSH. |
203
|
|
|
* |
204
|
|
|
* @return $this |
205
|
|
|
*/ |
206
|
|
|
public function isTypeNoPush(): self |
207
|
|
|
{ |
208
|
|
|
$this->notificationType = NotificationType::NO_PUSH; |
209
|
|
|
|
210
|
|
|
return $this; |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
/** |
214
|
|
|
* Helper to set messaging type as RESPONSE. |
215
|
|
|
* |
216
|
|
|
* @return $this |
217
|
|
|
*/ |
218
|
|
|
public function isResponse(): self |
219
|
|
|
{ |
220
|
|
|
$this->messagingType = MessagingType::RESPONSE; |
221
|
|
|
|
222
|
|
|
return $this; |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
/** |
226
|
|
|
* Helper to set messaging type as UPDATE. |
227
|
|
|
* |
228
|
|
|
* @return $this |
229
|
|
|
*/ |
230
|
|
|
public function isUpdate(): self |
231
|
|
|
{ |
232
|
|
|
$this->messagingType = MessagingType::UPDATE; |
233
|
|
|
|
234
|
|
|
return $this; |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
/** |
238
|
|
|
* Helper to set messaging type as MESSAGE_TAG. |
239
|
|
|
* |
240
|
|
|
* @param $messageTag |
241
|
|
|
* |
242
|
|
|
* @return $this |
243
|
|
|
*/ |
244
|
|
|
public function isMessageTag($messageTag): self |
245
|
|
|
{ |
246
|
|
|
$this->messagingType = MessagingType::MESSAGE_TAG; |
247
|
|
|
$this->messageTag = $messageTag; |
248
|
|
|
|
249
|
|
|
return $this; |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
/** |
253
|
|
|
* Add up to 10 cards to be displayed in a carousel. |
254
|
|
|
* |
255
|
|
|
* @param array $cards |
256
|
|
|
* |
257
|
|
|
* @throws CouldNotCreateMessage |
258
|
|
|
* @return $this |
259
|
|
|
*/ |
260
|
|
|
public function cards(array $cards): self |
261
|
|
|
{ |
262
|
|
|
if (count($cards) > 10) { |
263
|
|
|
throw CouldNotCreateMessage::messageCardsLimitExceeded(); |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
$this->cards = $cards; |
267
|
|
|
|
268
|
|
|
return $this; |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
/** |
272
|
|
|
* Determine if user id is not given. |
273
|
|
|
* |
274
|
|
|
* @return bool |
275
|
|
|
*/ |
276
|
|
|
public function toNotGiven(): bool |
277
|
|
|
{ |
278
|
|
|
return !isset($this->recipient); |
279
|
|
|
} |
280
|
|
|
|
281
|
|
|
/** |
282
|
|
|
* Convert the object into something JSON serializable. |
283
|
|
|
* |
284
|
|
|
* @throws CouldNotCreateMessage |
285
|
|
|
* @return mixed |
286
|
|
|
*/ |
287
|
|
|
public function jsonSerialize() |
288
|
|
|
{ |
289
|
|
|
return $this->toArray(); |
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
/** |
293
|
|
|
* Returns message payload for JSON conversion. |
294
|
|
|
* |
295
|
|
|
* @throws CouldNotCreateMessage |
296
|
|
|
* @return array |
297
|
|
|
*/ |
298
|
|
|
public function toArray(): array |
299
|
|
|
{ |
300
|
|
|
if ($this->hasAttachment) { |
301
|
|
|
return $this->attachmentMessageToArray(); |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
if ($this->hasText) { |
305
|
|
|
// check if it has buttons |
306
|
|
|
if (count($this->buttons) > 0) { |
307
|
|
|
return $this->buttonMessageToArray(); |
308
|
|
|
} |
309
|
|
|
|
310
|
|
|
return $this->textMessageToArray(); |
311
|
|
|
} |
312
|
|
|
|
313
|
|
|
if (count($this->cards) > 0) { |
314
|
|
|
return $this->genericMessageToArray(); |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
throw CouldNotCreateMessage::dataNotProvided(); |
318
|
|
|
} |
319
|
|
|
|
320
|
|
|
/** |
321
|
|
|
* Returns message for simple text message. |
322
|
|
|
* |
323
|
|
|
* @return array |
324
|
|
|
*/ |
325
|
|
|
protected function textMessageToArray(): array |
326
|
|
|
{ |
327
|
|
|
$message = []; |
328
|
|
|
$message['recipient'][$this->recipientType] = $this->recipient; |
329
|
|
|
$message['notification_type'] = $this->notificationType; |
330
|
|
|
$message['message']['text'] = $this->text; |
331
|
|
|
$message['messaging_type'] = $this->messagingType; |
332
|
|
|
|
333
|
|
|
if (filled($this->messageTag)) { |
334
|
|
|
$message['tag'] = $this->messageTag; |
335
|
|
|
} |
336
|
|
|
|
337
|
|
|
return $message; |
338
|
|
|
} |
339
|
|
|
|
340
|
|
|
/** |
341
|
|
|
* Returns message for attachment message. |
342
|
|
|
* |
343
|
|
|
* @return array |
344
|
|
|
*/ |
345
|
|
|
protected function attachmentMessageToArray(): array |
346
|
|
|
{ |
347
|
|
|
$message = []; |
348
|
|
|
$message['recipient'][$this->recipientType] = $this->recipient; |
349
|
|
|
$message['notification_type'] = $this->notificationType; |
350
|
|
|
$message['message']['attachment']['type'] = $this->attachmentType; |
351
|
|
|
$message['message']['attachment']['payload']['url'] = $this->attachmentUrl; |
352
|
|
|
$message['messaging_type'] = $this->messagingType; |
353
|
|
|
|
354
|
|
|
if (filled($this->messageTag)) { |
355
|
|
|
$message['tag'] = $this->messageTag; |
356
|
|
|
} |
357
|
|
|
|
358
|
|
|
return $message; |
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
/** |
362
|
|
|
* Returns message for Generic Template message. |
363
|
|
|
* |
364
|
|
|
* @return array |
365
|
|
|
*/ |
366
|
|
|
protected function genericMessageToArray(): array |
367
|
|
|
{ |
368
|
|
|
$message = []; |
369
|
|
|
$message['recipient'][$this->recipientType] = $this->recipient; |
370
|
|
|
$message['notification_type'] = $this->notificationType; |
371
|
|
|
$message['message']['attachment']['type'] = 'template'; |
372
|
|
|
$message['message']['attachment']['payload']['template_type'] = 'generic'; |
373
|
|
|
$message['message']['attachment']['payload']['elements'] = $this->cards; |
374
|
|
|
$message['messaging_type'] = $this->messagingType; |
375
|
|
|
|
376
|
|
|
if (filled($this->messageTag)) { |
377
|
|
|
$message['tag'] = $this->messageTag; |
378
|
|
|
} |
379
|
|
|
|
380
|
|
|
return $message; |
381
|
|
|
} |
382
|
|
|
|
383
|
|
|
/** |
384
|
|
|
* Returns message for Button Template message. |
385
|
|
|
* |
386
|
|
|
* @return array |
387
|
|
|
*/ |
388
|
|
|
protected function buttonMessageToArray(): array |
389
|
|
|
{ |
390
|
|
|
$message = []; |
391
|
|
|
$message['recipient'][$this->recipientType] = $this->recipient; |
392
|
|
|
$message['notification_type'] = $this->notificationType; |
393
|
|
|
$message['message']['attachment']['type'] = 'template'; |
394
|
|
|
$message['message']['attachment']['payload']['template_type'] = 'button'; |
395
|
|
|
$message['message']['attachment']['payload']['text'] = $this->text; |
396
|
|
|
$message['message']['attachment']['payload']['buttons'] = $this->buttons; |
397
|
|
|
$message['messaging_type'] = $this->messagingType; |
398
|
|
|
|
399
|
|
|
if (filled($this->messageTag)) { |
400
|
|
|
$message['tag'] = $this->messageTag; |
401
|
|
|
} |
402
|
|
|
|
403
|
|
|
return $message; |
404
|
|
|
} |
405
|
|
|
} |
406
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.