Completed
Push — master ( 33568f...080898 )
by Elf
01:35
created

Message::send()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 6

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 19
ccs 11
cts 11
cp 1
rs 8.8571
cc 6
eloc 10
nc 4
nop 0
crap 6
1
<?php
2
3
namespace ElfSundae\BearyChat;
4
5
use JsonSerializable;
6
7
class Message implements JsonSerializable
8
{
9
    /**
10
     * The BearyChat client for sending message.
11
     *
12
     * @var \ElfSundae\BearyChat\Client
13
     */
14
    protected $client;
15
16
    /**
17
     * The text to be sent with the message.
18
     *
19
     * @var string
20
     */
21
    protected $text;
22
23
    /**
24
     * The notification for the text.
25
     *
26
     * @var string
27
     */
28
    protected $notification;
29
30
    /**
31
     * Indicates the text field should be parsed as markdown syntax.
32
     *
33
     * @var bool
34
     */
35
    protected $markdown;
36
37
    /**
38
     * The channel that the message should be sent to.
39
     *
40
     * @var string
41
     */
42
    protected $channel;
43
44
    /**
45
     * The user that the message should be sent to.
46
     *
47
     * @var string
48
     */
49
    protected $user;
50
51
    /**
52
     * The attachments to be sent.
53
     *
54
     * @var array
55
     */
56
    protected $attachments = [];
57
58
    /**
59
     * The default values for each attachment.
60
     *
61
     * @var array
62
     */
63
    protected $attachmentDefaults = [];
64
65
    /**
66
     * Create a new message.
67
     *
68
     * @param  \ElfSundae\BearyChat\Client|null $client
69
     */
70 22
    public function __construct(Client $client = null)
71
    {
72 22
        if ($this->client = $client) {
73 5
            $this->configureDefaults($client->getMessageDefaults(), true);
74 5
        }
75 22
    }
76
77
    /**
78
     * Get the BearyChat client for sending message.
79
     *
80
     * @return \ElfSundae\BearyChat\Client
81
     */
82 2
    public function getClient()
83
    {
84 2
        return $this->client;
85
    }
86
87
    /**
88
     * Get the text.
89
     *
90
     * @return string
91
     */
92 7
    public function getText()
93
    {
94 7
        return $this->text;
95
    }
96
97
    /**
98
     * Set the text.
99
     *
100
     * @param  string  $text
101
     * @return $this
102
     */
103 6
    public function setText($text)
104
    {
105 6
        $this->text = $text ? (string) $text : null;
106
107 6
        return $this;
108
    }
109
110
    /**
111
     * Set the text.
112
     *
113
     * @param  string  $text
114
     * @return $this
115
     */
116 4
    public function text($text)
117
    {
118 4
        return $this->setText($text);
119
    }
120
121
    /**
122
     * Get the notification.
123
     *
124
     * @return string
125
     */
126 7
    public function getNotification()
127
    {
128 7
        return $this->notification;
129
    }
130
131
    /**
132
     * Set the notification.
133
     *
134
     * @param  string  $notification
135
     * @return $this
136
     */
137 4
    public function setNotification($notification)
138
    {
139 4
        $this->notification = $notification ? (string) $notification : null;
140
141 4
        return $this;
142
    }
143
144
    /**
145
     * Set the notification.
146
     *
147
     * @param  string  $notification
148
     * @return $this
149
     */
150 1
    public function notification($notification)
151
    {
152 1
        return $this->setNotification($notification);
153
    }
154
155
    /**
156
     * Get the markdown.
157
     *
158
     * @return bool
159
     */
160 7
    public function getMarkdown()
161
    {
162 7
        return $this->markdown;
163
    }
164
165
    /**
166
     * Set the markdown.
167
     *
168
     * @param  bool $markdown
169
     * @return $this
170
     */
171 3
    public function setMarkdown($markdown)
172
    {
173 3
        $this->markdown = (bool) $markdown;
174
175 3
        return $this;
176
    }
177
178
    /**
179
     * Set the markdown.
180
     *
181
     * @param  bool $markdown
182
     * @return $this
183
     */
184 1
    public function markdown($markdown = true)
185
    {
186 1
        return $this->setMarkdown($markdown);
187
    }
188
189
    /**
190
     * Get the channel which the message should be sent to.
191
     *
192
     * @return string
193
     */
194 10
    public function getChannel()
195
    {
196 10
        return $this->channel;
197
    }
198
199
    /**
200
     * Set the channel which the message should be sent to.
201
     *
202
     * @param  string  $channel
203
     * @return $this
204
     */
205 6
    public function setChannel($channel)
206
    {
207 6
        $this->removeTarget();
208
209 6
        if ($channel) {
210 6
            $this->channel = (string) $channel;
211 6
        }
212
213 6
        return $this;
214
    }
215
216
    /**
217
     * Set the channel which the message should be sent to.
218
     *
219
     * @param  string  $channel
220
     * @return $this
221
     */
222 4
    public function channel($channel)
223
    {
224 4
        return $this->setChannel($channel);
225
    }
226
227
    /**
228
     * Get the user which the message should be sent to.
229
     *
230
     * @return string
231
     */
232 10
    public function getUser()
233
    {
234 10
        return $this->user;
235
    }
236
237
    /**
238
     * Set the user which the message should be sent to.
239
     *
240
     * @param  string  $user
241
     * @return $this
242
     */
243 10
    public function setUser($user)
244
    {
245 10
        $this->removeTarget();
246
247 10
        if ($user) {
248 10
            $this->user = (string) $user;
249 10
        }
250
251 10
        return $this;
252
    }
253
254
    /**
255
     * Set the user which the message should be sent to.
256
     *
257
     * @param  string  $user
258
     * @return $this
259
     */
260 4
    public function user($user)
261
    {
262 4
        return $this->setUser($user);
263
    }
264
265
    /**
266
     * Get the target that the message should be sent to:
267
     * `#channel` or `@user` or null.
268
     *
269
     * @return string
270
     */
271 4
    public function getTarget()
272
    {
273 4
        if ($this->channel) {
274 1
            return '#'.$this->channel;
275
        }
276
277 4
        if ($this->user) {
278 4
            return '@'.$this->user;
279
        }
280 4
    }
281
282
    /**
283
     * Set the target (user or channel) that the message should be sent to.
284
     *
285
     * @param  string  $target  @user, #channel, channel, null
286
     * @return $this
287
     */
288 3
    public function setTarget($target)
289
    {
290 3
        $this->removeTarget();
291
292 3
        if ($target = (string) $target) {
293 3
            $mark = mb_substr($target, 0, 1);
294 3
            $to = mb_substr($target, 1);
295
296 3
            if ($mark === '@') {
297 3
                $this->setUser($to);
298 3
            } elseif ($mark === '#') {
299 1
                $this->setChannel($to);
300 1
            } else {
301 2
                $this->setChannel($target);
302
            }
303 3
        }
304
305 3
        return $this;
306
    }
307
308
    /**
309
     * Remove the target, then this message will be sent to
310
     * the webhook defined target.
311
     *
312
     * @return $this
313
     */
314 10
    public function removeTarget()
315
    {
316 10
        $this->channel = $this->user = null;
317
318 10
        return $this;
319
    }
320
321
    /**
322
     * Set the target.
323
     *
324
     * @param  string  $target
325
     * @return $this
326
     */
327 1
    public function target($target)
328
    {
329 1
        return $this->setTarget($target);
330
    }
331
332
    /**
333
     * Set the target.
334
     *
335
     * @param  string  $target
336
     * @return $this
337
     */
338 3
    public function to($target)
339
    {
340 3
        return $this->setTarget($target);
341
    }
342
343
    /**
344
     * Get the attachments defaults.
345
     *
346
     * @return array
347
     */
348 1
    public function getAttachmentDefaults()
349
    {
350 1
        return $this->attachmentDefaults;
351
    }
352
353
    /**
354
     * Set the attachments defaults.
355
     *
356
     * @param  array  $defaults
357
     * @return $this
358
     */
359 2
    public function setAttachmentDefaults($defaults)
360
    {
361 2
        $this->attachmentDefaults = (array) $defaults;
362
363 2
        return $this;
364
    }
365
366
    /**
367
     * Get the attachments for the message.
368
     *
369
     * @return array
370
     */
371 10
    public function getAttachments()
372
    {
373 10
        return $this->attachments;
374
    }
375
376
    /**
377
     * Set the attachments for the message.
378
     *
379
     * @param  mixed  $attachments
380
     * @return $this
381
     */
382 4
    public function setAttachments($attachments)
383
    {
384 4
        $this->removeAttachments();
385
386 4
        if (is_array($attachments)) {
387 4
            foreach ($attachments as $attachment) {
388 2
                $this->addAttachment($attachment);
389 4
            }
390 4
        }
391
392 4
        return $this;
393
    }
394
395
    /**
396
     * Set the attachments for the message.
397
     *
398
     * @param  mixed  $attachments
399
     * @return $this
400
     */
401 1
    public function attachments($attachments)
402
    {
403 1
        return $this->setAttachments($attachments);
404
    }
405
406
    /**
407
     * Add an attachment to the message.
408
     *
409
     * The parameter can be an payload array that contains all of attachment's fields.
410
     * The parameters can also be attachment's fields that in order of
411
     * text, title, images and color. Except the text, other parameters
412
     * can be ignored.
413
     *
414
     * @param  mixed  $attachment
415
     * @return $this
416
     */
417 9
    public function addAttachment($attachment)
418
    {
419 9
        if (! is_array($attachment)) {
420 8
            $attachment = call_user_func_array([$this, 'getAttachmentPayload'], func_get_args());
421 8
        } elseif (
422 3
            ! empty($attachment['images']) &&
423 1
            $images = $this->getImagesPayload($attachment['images'])
424 3
        ) {
425 1
            $attachment['images'] = $images;
426 1
        }
427
428 9
        if (! empty($attachment)) {
429 9
            $attachment += $this->attachmentDefaults;
430
431 9
            $this->attachments[] = $attachment;
432 9
        }
433
434 9
        return $this;
435
    }
436
437
    /**
438
     * Get payload for an attachment.
439
     *
440
     * @param  mixed  $text
441
     * @param  mixed  $title
442
     * @param  mixed  $images
443
     * @param  mixed  $color
444
     * @return array
445
     */
446 8
    protected function getAttachmentPayload($text = null, $title = null, $images = null, $color = null)
447
    {
448 8
        $attachment = [];
449
450 8
        if ($text) {
451 8
            $attachment['text'] = $this->stringValue($text);
452 8
        }
453
454 8
        if ($title) {
455 4
            $attachment['title'] = $this->stringValue($title);
456 4
        }
457
458 8
        if ($images = $this->getImagesPayload($images)) {
459 3
            $attachment['images'] = $images;
460 3
        }
461
462 8
        if ($color) {
463 2
            $attachment['color'] = (string) $color;
464 2
        }
465
466 8
        return $attachment;
467
    }
468
469
    /**
470
     * Get payload for images.
471
     *
472
     * @param  mixed  $value
473
     * @return array
474
     */
475 8
    protected function getImagesPayload($value)
476
    {
477 8
        $images = [];
478
479 8
        foreach ((array) $value as $img) {
480 3
            if (! empty($img['url'])) {
481
                $img = $img['url'];
482
            }
483
484 3
            if (is_string($img) && ! empty($img)) {
485 3
                $images[] = ['url' => $img];
486 3
            }
487 8
        }
488
489 8
        return $images;
490
    }
491
492
    /**
493
     * Convert any type to string.
494
     *
495
     * @param  mixed  $value
496
     * @param  int  $jsonOptions
497
     * @return string
498
     */
499 8
    protected function stringValue($value, $jsonOptions = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
500
    {
501 8
        if (is_string($value)) {
502 8
            return $value;
503
        }
504
505 1
        if (method_exists($value, '__toString')) {
506
            return (string) $value;
507
        }
508
509 1
        if (method_exists($value, 'toArray')) {
510
            $value = $value->toArray();
511
        }
512
513 1
        return json_encode($value, $jsonOptions);
514
    }
515
516
    /**
517
     * Add an attachment to the message.
518
     * It alias to `addAttachment`.
519
     *
520
     * @return $this
521
     */
522 5
    public function add()
523
    {
524 5
        return call_user_func_array([$this, 'addAttachment'], func_get_args());
525
    }
526
527
    /**
528
     * Add an image attachment to the message.
529
     *
530
     * @param  string|string[]  $image
531
     * @param  string  $desc
532
     * @param  string  $title
533
     * @return $this
534
     */
535 1
    public function addImage($image, $desc = null, $title = null)
536
    {
537 1
        return $this->addAttachment($desc, $title, $image);
538
    }
539
540
    /**
541
     * Remove attachment[s] for the message.
542
     *
543
     * @return $this
544
     */
545 5
    public function removeAttachments()
546
    {
547 5
        if (func_num_args() > 0) {
548 1
            $indices = is_array(func_get_arg(0)) ? func_get_arg(0) : func_get_args();
549
550 1
            foreach ($indices as $index) {
551 1
                unset($this->attachments[$index]);
552 1
            }
553
554 1
            $this->attachments = array_values($this->attachments);
555 1
        } else {
556 5
            $this->attachments = [];
557
        }
558
559 5
        return $this;
560
    }
561
562
    /**
563
     * Remove attachment[s] for the message.
564
     * It alias to `removeAttachments`.
565
     *
566
     * @return $this
567
     */
568 1
    public function remove()
569
    {
570 1
        return call_user_func_array([$this, 'removeAttachments'], func_get_args());
571
    }
572
573
    /**
574
     * Configure message defaults.
575
     *
576
     * @param  array  $defaults
577
     * @param  bool  $force
578
     * @return $this
579
     */
580 6
    public function configureDefaults(array $defaults, $force = false)
581
    {
582 6
        if (! $force && ! empty($this->toArray())) {
583 1
            return $this;
584
        }
585
586 6
        $attachmentDefaults = $this->attachmentDefaults;
587
588 6
        foreach (MessageDefaults::allKeys() as $key) {
589 6
            if (! isset($defaults[$key]) || is_null($value = $defaults[$key])) {
590 6
                continue;
591
            }
592
593 3
            if (strpos($key, 'attachment_') !== false) {
594 3
                if ($key = substr($key, strlen('attachment_'))) {
595 3
                    $attachmentDefaults[$key] = $value;
596 3
                }
597 3
            } else {
598 3
                if (! is_null($this->getTarget()) &&
599 3
                    ($key == MessageDefaults::USER || $key == MessageDefaults::CHANNEL)
600 3
                ) {
601 1
                    continue;
602
                }
603
604 3
                if ($suffix = $this->studlyCase($key)) {
605 3
                    $getMethod = 'get'.$suffix;
606 3
                    $setMethod = 'set'.$suffix;
607
                    if (
608 3
                        method_exists($this, $getMethod) &&
609 3
                        is_null($this->{$getMethod}()) &&
610 3
                        method_exists($this, $setMethod)
611 3
                    ) {
612 3
                        $this->{$setMethod}($value);
613 3
                    }
614 3
                }
615
            }
616 6
        }
617
618 6
        if ($attachmentDefaults != $this->attachmentDefaults) {
619 3
            $this->attachmentDefaults = $attachmentDefaults;
620 3
            $this->setAttachments($this->attachments);
621 3
        }
622
623 6
        return $this;
624
    }
625
626
    /**
627
     * Convert a string to studly caps case.
628
     *
629
     * @param  string  $string
630
     * @return string
631
     */
632 3
    protected function studlyCase($string)
633
    {
634 3
        return str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $string)));
635
    }
636
637
    /**
638
     * Conveniently set message content.
639
     *
640
     * The parameters may be:
641
     * `($text, $markdown, $notification)`
642
     * or `($text, $attachment_text, $attachment_title, $attachment_images, $attachment_color)`.
643
     *
644
     * @return $this
645
     */
646 2
    public function content()
647
    {
648 2
        $arguments = func_get_args();
649 2
        $count = count($arguments);
650
651 2
        if ($count > 0) {
652 2
            $this->setText($arguments[0]);
653 2
        }
654
655 2
        if ($count > 1) {
656 2
            if (is_bool($arguments[1])) {
657 2
                $this->setMarkdown($arguments[1]);
658
659 2
                if ($count > 2) {
660 1
                    $this->setNotification($arguments[2]);
661 1
                }
662 2
            } else {
663 1
                call_user_func_array([$this, 'addAttachment'], array_slice($arguments, 1));
664
            }
665 2
        }
666
667 2
        return $this;
668
    }
669
670
    /**
671
     * Convert the message to an array.
672
     *
673
     * @return array
674
     */
675 6
    public function toArray()
676
    {
677 6
        return array_filter(
678
            [
679 6
                'text' => $this->getText(),
680 6
                'notification' => $this->getNotification(),
681 6
                'markdown' => $this->getMarkdown(),
682 6
                'channel' => $this->getChannel(),
683 6
                'user' => $this->getUser(),
684 6
                'attachments' => $this->getAttachments(),
685 6
            ],
686 6
            function ($value, $key) {
687
                return ! (
688 6
                    is_null($value) ||
689 6
                    ($key === 'markdown' && $value === true) ||
690 6
                    (is_array($value) && empty($value))
691 6
                );
692 6
            },
693
            ARRAY_FILTER_USE_BOTH
694 6
        );
695
    }
696
697
    /**
698
     * Convert the message to JSON string.
699
     *
700
     * @param  int  $options
701
     * @return string
702
     */
703 1
    public function toJson($options = 0)
704
    {
705 1
        return json_encode($this->jsonSerialize(), $options);
706
    }
707
708
    /**
709
     * Serializes the object to a value that can be serialized natively by json_encode().
710
     *
711
     * @return array
712
     */
713 1
    public function jsonSerialize()
714
    {
715 1
        return $this->toArray();
716
    }
717
718
    /**
719
     * Send the message.
720
     *
721
     * The parameters accepts the same format of `content` method.
722
     *
723
     * @return bool
724
     */
725 2
    public function send()
726
    {
727 2
        if (! $this->client) {
728 1
            return false;
729
        }
730
731
        if (
732 2
            1 == func_num_args() &&
733 1
            (is_array(func_get_arg(0)) || is_object(func_get_arg(0)))
734 2
        ) {
735 1
            return $this->client->sendMessage(func_get_arg(0));
736
        }
737
738 2
        if (func_num_args() > 0) {
739 2
            call_user_func_array([$this, 'content'], func_get_args());
740 2
        }
741
742 2
        return $this->client->sendMessage($this);
743
    }
744
745
    /**
746
     * Send the message to the given target.
747
     *
748
     * @param  mixed  $target
749
     * @return bool
750
     */
751 1
    public function sendTo($target)
752
    {
753 1
        $this->to($target);
754
755 1
        return call_user_func_array([$this, 'send'], array_slice(func_get_args(), 1));
756
    }
757
758
    /**
759
     * Convert the message to its string representation.
760
     *
761
     * @return string
762
     */
763 1
    public function __toString()
764
    {
765 1
        return $this->toJson();
766
    }
767
}
768