Completed
Push — master ( 7b34b6...f8e14a )
by Elf
01:34
created

Message::fillDefaults()   B

Complexity

Conditions 8
Paths 4

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 8

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 21
ccs 12
cts 12
cp 1
rs 7.1428
cc 8
eloc 13
nc 4
nop 2
crap 8
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 23
    public function __construct(Client $client = null)
71
    {
72 23
        if ($this->client = $client) {
73 5
            $this->configureDefaults($client->getMessageDefaults(), true);
74
        }
75 23
    }
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 8
    public function getText()
93
    {
94 8
        return $this->text;
95
    }
96
97
    /**
98
     * Set the text.
99
     *
100
     * @param  string  $text
101
     * @return $this
102
     */
103 7
    public function setText($text)
104
    {
105 7
        $this->text = $text ? (string) $text : null;
106
107 7
        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 8
    public function getNotification()
127
    {
128 8
        return $this->notification;
129
    }
130
131
    /**
132
     * Set the notification.
133
     *
134
     * @param  string  $notification
135
     * @return $this
136
     */
137 5
    public function setNotification($notification)
138
    {
139 5
        $this->notification = $notification ? (string) $notification : null;
140
141 5
        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 8
    public function getMarkdown()
161
    {
162 8
        return $this->markdown;
163
    }
164
165
    /**
166
     * Set the markdown.
167
     *
168
     * @param  bool $markdown
169
     * @return $this
170
     */
171 4
    public function setMarkdown($markdown)
172
    {
173 4
        $this->markdown = (bool) $markdown;
174
175 4
        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 11
    public function getChannel()
195
    {
196 11
        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
        }
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 11
    public function getUser()
233
    {
234 11
        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
        }
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 2
            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 2
            } elseif ($mark === '#') {
299 1
                $this->setChannel($to);
300
            } else {
301 2
                $this->setChannel($target);
302
            }
303
        }
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 8
    public function setAttachmentDefaults($defaults)
360
    {
361 8
        if ($this->attachmentDefaults != ($defaults = (array) $defaults)) {
362 5
            $this->attachmentDefaults = $defaults;
363 5
            $this->setAttachments($this->attachments);
364
        }
365
366 8
        return $this;
367
    }
368
369
    /**
370
     * Get the attachments for the message.
371
     *
372
     * @return array
373
     */
374 11
    public function getAttachments()
375
    {
376 11
        return $this->attachments;
377
    }
378
379
    /**
380
     * Set the attachments for the message.
381
     *
382
     * @param  mixed  $attachments
383
     * @return $this
384
     */
385 6
    public function setAttachments($attachments)
386
    {
387 6
        $this->removeAttachments();
388
389 6
        if (is_array($attachments)) {
390 6
            foreach ($attachments as $attachment) {
391 3
                $this->addAttachment($attachment);
392
            }
393
        }
394
395 6
        return $this;
396
    }
397
398
    /**
399
     * Set the attachments for the message.
400
     *
401
     * @param  mixed  $attachments
402
     * @return $this
403
     */
404 1
    public function attachments($attachments)
405
    {
406 1
        return $this->setAttachments($attachments);
407
    }
408
409
    /**
410
     * Add an attachment to the message.
411
     *
412
     * The parameter can be an payload array that contains all of attachment's fields.
413
     * The parameters can also be attachment's fields that in order of
414
     * text, title, images and color. Except the text, other parameters
415
     * can be ignored.
416
     *
417
     * @param  mixed  $attachment
418
     * @return $this
419
     */
420 10
    public function addAttachment($attachment)
421
    {
422 10
        if (! is_array($attachment)) {
423 9
            $attachment = call_user_func_array([$this, 'getAttachmentPayload'], func_get_args());
424
        } elseif (
425 4
            ! empty($attachment['images']) &&
426 4
            $images = $this->getImagesPayload($attachment['images'])
427
        ) {
428 1
            $attachment['images'] = $images;
429
        }
430
431 10
        if (! empty($attachment)) {
432 10
            $attachment += $this->attachmentDefaults;
433
434 10
            $this->attachments[] = $attachment;
435
        }
436
437 10
        return $this;
438
    }
439
440
    /**
441
     * Get payload for an attachment.
442
     *
443
     * @param  mixed  $text
444
     * @param  mixed  $title
445
     * @param  mixed  $images
446
     * @param  mixed  $color
447
     * @return array
448
     */
449 9
    protected function getAttachmentPayload($text = null, $title = null, $images = null, $color = null)
450
    {
451 9
        $attachment = [];
452
453 9
        if ($text) {
454 9
            $attachment['text'] = $this->stringValue($text);
455
        }
456
457 9
        if ($title) {
458 5
            $attachment['title'] = $this->stringValue($title);
459
        }
460
461 9
        if ($images = $this->getImagesPayload($images)) {
462 4
            $attachment['images'] = $images;
463
        }
464
465 9
        if ($color) {
466 3
            $attachment['color'] = (string) $color;
467
        }
468
469 9
        return $attachment;
470
    }
471
472
    /**
473
     * Get payload for images.
474
     *
475
     * @param  mixed  $value
476
     * @return array
477
     */
478 9
    protected function getImagesPayload($value)
479
    {
480 9
        $images = [];
481
482 9
        foreach ((array) $value as $img) {
483 4
            if (! empty($img['url'])) {
484
                $img = $img['url'];
485
            }
486
487 4
            if (is_string($img) && ! empty($img)) {
488 4
                $images[] = ['url' => $img];
489
            }
490
        }
491
492 9
        return $images;
493
    }
494
495
    /**
496
     * Convert any type to string.
497
     *
498
     * @param  mixed  $value
499
     * @param  int  $jsonOptions
500
     * @return string
501
     */
502 9
    protected function stringValue($value, $jsonOptions = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
503
    {
504 9
        if (is_string($value)) {
505 9
            return $value;
506
        }
507
508 1
        if (method_exists($value, '__toString')) {
509
            return (string) $value;
510
        }
511
512 1
        if (method_exists($value, 'toArray')) {
513
            $value = $value->toArray();
514
        }
515
516 1
        return json_encode($value, $jsonOptions);
517
    }
518
519
    /**
520
     * Add an attachment to the message.
521
     * It alias to `addAttachment`.
522
     *
523
     * @return $this
524
     */
525 6
    public function add()
526
    {
527 6
        return call_user_func_array([$this, 'addAttachment'], func_get_args());
528
    }
529
530
    /**
531
     * Add an image attachment to the message.
532
     *
533
     * @param  string|string[]  $image
534
     * @param  string  $desc
535
     * @param  string  $title
536
     * @return $this
537
     */
538 1
    public function addImage($image, $desc = null, $title = null)
539
    {
540 1
        return $this->addAttachment($desc, $title, $image);
541
    }
542
543
    /**
544
     * Remove attachment[s] for the message.
545
     *
546
     * @return $this
547
     */
548 7
    public function removeAttachments()
549
    {
550 7
        if (func_num_args() > 0) {
551 1
            $indices = is_array(func_get_arg(0)) ? func_get_arg(0) : func_get_args();
552
553 1
            foreach ($indices as $index) {
554 1
                unset($this->attachments[$index]);
555
            }
556
557 1
            $this->attachments = array_values($this->attachments);
558
        } else {
559 7
            $this->attachments = [];
560
        }
561
562 7
        return $this;
563
    }
564
565
    /**
566
     * Remove attachment[s] for the message.
567
     * It alias to `removeAttachments`.
568
     *
569
     * @return $this
570
     */
571 1
    public function remove()
572
    {
573 1
        return call_user_func_array([$this, 'removeAttachments'], func_get_args());
574
    }
575
576
    /**
577
     * Configure message defaults.
578
     *
579
     * @param  array  $defaults
580
     * @param  bool  $force
581
     * @return $this
582
     */
583 6
    public function configureDefaults(array $defaults, $force = false)
584
    {
585 6
        if ($force || empty($this->toArray())) {
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 3
                    if (strpos($key, 'attachment_') !== false) {
591 3
                        if ($key = substr($key, strlen('attachment_'))) {
592 3
                            $attachmentDefaults[$key] = $value;
593
                        }
594
                    } else {
595 6
                        $this->fillDefaults($key, $value);
596
                    }
597
                }
598
            }
599
600 6
            $this->setAttachmentDefaults($attachmentDefaults);
601
        }
602
603 6
        return $this;
604
    }
605
606
    /**
607
     * Fill with message defaults.
608
     *
609
     * @param  string  $key
610
     * @param  mixed  $value
611
     * @return void
612
     */
613 3
    protected function fillDefaults($key, $value)
614
    {
615
        if (
616 3
            ($key === MessageDefaults::USER || $key === MessageDefaults::CHANNEL) &&
617 3
            (! is_null($this->getTarget()))
618
        ) {
619 1
            return;
620
        }
621
622 3
        if ($suffix = $this->studlyCase($key)) {
623 3
            $getMethod = 'get'.$suffix;
624 3
            $setMethod = 'set'.$suffix;
625
            if (
626 3
                method_exists($this, $getMethod) &&
627 3
                is_null($this->{$getMethod}()) &&
628 3
                method_exists($this, $setMethod)
629
            ) {
630 3
                $this->{$setMethod}($value);
631
            }
632
        }
633 3
    }
634
635
    /**
636
     * Convert a string to studly caps case.
637
     *
638
     * @param  string  $string
639
     * @return string
640
     */
641 3
    protected function studlyCase($string)
642
    {
643 3
        return str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $string)));
644
    }
645
646
    /**
647
     * Conveniently set message content.
648
     *
649
     * The parameters may be:
650
     * `($text, $markdown, $notification)`
651
     * or `($text, $attachment_text, $attachment_title, $attachment_images, $attachment_color)`.
652
     *
653
     * @return $this
654
     */
655 3
    public function content()
656
    {
657 3
        $arguments = func_get_args();
658 3
        $count = count($arguments);
659
660 3
        if ($count > 0) {
661 3
            $this->setText($arguments[0]);
662
        }
663
664 3
        if ($count > 1) {
665 3
            if (is_bool($arguments[1])) {
666 3
                $this->setMarkdown($arguments[1]);
667
668 3
                if ($count > 2) {
669 3
                    $this->setNotification($arguments[2]);
670
                }
671
            } else {
672 2
                call_user_func_array([$this, 'addAttachment'], array_slice($arguments, 1));
673
            }
674
        }
675
676 3
        return $this;
677
    }
678
679
    /**
680
     * Convert the message to an array.
681
     *
682
     * @return array
683
     */
684 7
    public function toArray()
685
    {
686 7
        return array_filter(
687
            [
688 7
                'text' => $this->getText(),
689 7
                'notification' => $this->getNotification(),
690 7
                'markdown' => $this->getMarkdown(),
691 7
                'channel' => $this->getChannel(),
692 7
                'user' => $this->getUser(),
693 7
                'attachments' => $this->getAttachments(),
694
            ],
695 7
            function ($value, $key) {
696
                return ! (
697 7
                    is_null($value) ||
698 7
                    ($key === 'markdown' && $value === true) ||
699 7
                    (is_array($value) && empty($value))
700
                );
701 7
            },
702 7
            ARRAY_FILTER_USE_BOTH
703
        );
704
    }
705
706
    /**
707
     * Convert the message to JSON string.
708
     *
709
     * @param  int  $options
710
     * @return string
711
     */
712 1
    public function toJson($options = 0)
713
    {
714 1
        return json_encode($this->jsonSerialize(), $options);
715
    }
716
717
    /**
718
     * Serializes the object to a value that can be serialized natively by json_encode().
719
     *
720
     * @return array
721
     */
722 1
    public function jsonSerialize()
723
    {
724 1
        return $this->toArray();
725
    }
726
727
    /**
728
     * Send the message.
729
     *
730
     * The parameters accepts the same format of `content` method.
731
     *
732
     * @return bool
733
     */
734 2
    public function send()
735
    {
736 2
        if (! $this->client) {
737 1
            return false;
738
        }
739
740
        if (
741 2
            1 == func_num_args() &&
742 2
            (is_array(func_get_arg(0)) || is_object(func_get_arg(0)))
743
        ) {
744 1
            return $this->client->sendMessage(func_get_arg(0));
745
        }
746
747 2
        if (func_num_args() > 0) {
748 2
            call_user_func_array([$this, 'content'], func_get_args());
749
        }
750
751 2
        return $this->client->sendMessage($this);
752
    }
753
754
    /**
755
     * Send the message to the given target.
756
     *
757
     * @param  mixed  $target
758
     * @return bool
759
     */
760 1
    public function sendTo($target)
761
    {
762 1
        $this->to($target);
763
764 1
        return call_user_func_array([$this, 'send'], array_slice(func_get_args(), 1));
765
    }
766
767
    /**
768
     * Convert the message to its string representation.
769
     *
770
     * @return string
771
     */
772 1
    public function __toString()
773
    {
774 1
        return $this->toJson();
775
    }
776
}
777