Completed
Push — master ( 894a20...09bd57 )
by Elf
03:21 queued 37s
created

Message::stringValue()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 5.2596

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 12
ccs 4
cts 7
cp 0.5714
rs 9.2
cc 4
eloc 6
nc 5
nop 2
crap 5.2596
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 3
            $attachment['title'] = $this->stringValue($title);
456 3
        }
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 (is_array($img) && isset($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 (method_exists($value, '__toString')) {
502
            return (string) $value;
503
        }
504
505 8
        if (method_exists($value, 'toArray')) {
506
            $value = $value->toArray();
507
        }
508
509 8
        return is_string($value) ? $value : json_encode($value, $jsonOptions);
510
    }
511
512
    /**
513
     * Add an attachment to the message.
514
     * It alias to `addAttachment`.
515
     *
516
     * @return $this
517
     */
518 5
    public function add()
519
    {
520 5
        return call_user_func_array([$this, 'addAttachment'], func_get_args());
521
    }
522
523
    /**
524
     * Add an image attachment to the message.
525
     *
526
     * @param  string|string[]  $image
527
     * @param  string  $desc
528
     * @return $this
529
     */
530 1
    public function addImage($image, $desc = null)
531
    {
532 1
        return $this->addAttachment($desc, null, $image);
533
    }
534
535
    /**
536
     * Remove attachment[s] for the message.
537
     *
538
     * @return $this
539
     */
540 5
    public function removeAttachments()
541
    {
542 5
        if (func_num_args() > 0) {
543 1
            $indices = is_array(func_get_arg(0)) ? func_get_arg(0) : func_get_args();
544
545 1
            foreach ($indices as $index) {
546 1
                unset($this->attachments[$index]);
547 1
            }
548
549 1
            $this->attachments = array_values($this->attachments);
550 1
        } else {
551 5
            $this->attachments = [];
552
        }
553
554 5
        return $this;
555
    }
556
557
    /**
558
     * Remove attachment[s] for the message.
559
     * It alias to `removeAttachments`.
560
     *
561
     * @return $this
562
     */
563 1
    public function remove()
564
    {
565 1
        return call_user_func_array([$this, 'removeAttachments'], func_get_args());
566
    }
567
568
    /**
569
     * Configure message defaults.
570
     *
571
     * @param  array  $defaults
572
     * @param  bool  $force
573
     * @return $this
574
     */
575 6
    public function configureDefaults(array $defaults, $force = false)
576
    {
577 6
        if (! $force && ! empty($this->toArray())) {
578 1
            return $this;
579
        }
580
581 6
        $attachmentDefaults = $this->attachmentDefaults;
582
583 6
        foreach (MessageDefaults::allKeys() as $key) {
584 6
            if (! isset($defaults[$key]) || is_null($value = $defaults[$key])) {
585 6
                continue;
586
            }
587
588 3
            if (strpos($key, 'attachment_') !== false) {
589 3
                if ($key = substr($key, strlen('attachment_'))) {
590 3
                    $attachmentDefaults[$key] = $value;
591 3
                }
592 3
            } else {
593 3
                if (! is_null($this->getTarget()) &&
594 3
                    ($key == MessageDefaults::USER || $key == MessageDefaults::CHANNEL)
595 3
                ) {
596 1
                    continue;
597
                }
598
599 3
                if ($suffix = $this->studlyCase($key)) {
600 3
                    $getMethod = 'get'.$suffix;
601 3
                    $setMethod = 'set'.$suffix;
602
                    if (
603 3
                        method_exists($this, $getMethod) &&
604 3
                        is_null($this->{$getMethod}()) &&
605 3
                        method_exists($this, $setMethod)
606 3
                    ) {
607 3
                        $this->{$setMethod}($value);
608 3
                    }
609 3
                }
610
            }
611 6
        }
612
613 6
        if ($attachmentDefaults != $this->attachmentDefaults) {
614 3
            $this->attachmentDefaults = $attachmentDefaults;
615 3
            $this->setAttachments($this->attachments);
616 3
        }
617
618 6
        return $this;
619
    }
620
621
    /**
622
     * Convert a string to studly caps case.
623
     *
624
     * @param  string  $string
625
     * @return string
626
     */
627 3
    protected function studlyCase($string)
628
    {
629 3
        return str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $string)));
630
    }
631
632
    /**
633
     * Convert the message to an array.
634
     *
635
     * @return array
636
     */
637 6
    public function toArray()
638
    {
639 6
        return array_filter(
640
            [
641 6
                'text' => $this->getText(),
642 6
                'notification' => $this->getNotification(),
643 6
                'markdown' => $this->getMarkdown(),
644 6
                'channel' => $this->getChannel(),
645 6
                'user' => $this->getUser(),
646 6
                'attachments' => $this->getAttachments(),
647 6
            ],
648 6
            function ($value, $key) {
649
                return ! (
650 6
                    is_null($value) ||
651 6
                    ($key === 'markdown' && $value === true) ||
652 6
                    (is_array($value) && empty($value))
653 6
                );
654 6
            },
655
            ARRAY_FILTER_USE_BOTH
656 6
        );
657
    }
658
659
    /**
660
     * Convert the message to JSON string.
661
     *
662
     * @param  int  $options
663
     * @return string
664
     */
665 1
    public function toJson($options = 0)
666
    {
667 1
        return json_encode($this->jsonSerialize(), $options);
668
    }
669
670
    /**
671
     * Serializes the object to a value that can be serialized natively by json_encode().
672
     *
673
     * @return array
674
     */
675 1
    public function jsonSerialize()
676
    {
677 1
        return $this->toArray();
678
    }
679
680
    /**
681
     * Send the message.
682
     *
683
     * The parameters can be `($text, $markdown, $notification)`, and the $text and
684
     * the $notification can be `null` that does not modify the exist field.
685
     * The parameters can also be
686
     * `($text, $attachment_text, $attachment_title, $attachment_images, $attachment_color)`.
687
     *
688
     * @return bool
689
     */
690 2
    public function send()
691
    {
692 2
        if (! $this->client) {
693 1
            return false;
694
        }
695
696 2
        if ($count = func_num_args()) {
697 2
            $firstArg = func_get_arg(0);
698
699 2
            if (1 === $count && (is_array($firstArg) || is_object($firstArg))) {
700 1
                return $this->client->sendMessage($firstArg);
701
            }
702
703 2
            if (! is_null($firstArg)) {
704 2
                $this->setText($firstArg);
705 2
            }
706
707 2
            if ($count > 1 && is_bool(func_get_arg(1))) {
708 2
                $this->setMarkdown(func_get_arg(1));
709
710 2
                if ($count > 2 && ! is_null(func_get_arg(2))) {
711 1
                    $this->setNotification(func_get_arg(2));
712 1
                }
713 2
            } elseif ($count > 1) {
714 1
                call_user_func_array(
715 1
                    [$this, 'addAttachment'],
716 1
                    array_slice(func_get_args(), 1)
717 1
                );
718 1
            }
719 2
        }
720
721 2
        return $this->client->sendMessage($this);
722
    }
723
724
    /**
725
     * Send the message to the given target.
726
     *
727
     * @param  mixed  $target
728
     * @return bool
729
     */
730 1
    public function sendTo($target)
731
    {
732 1
        $this->to($target);
733
734 1
        return call_user_func_array([$this, 'send'], array_slice(func_get_args(), 1));
735
    }
736
737
    /**
738
     * Convert the message to its string representation.
739
     *
740
     * @return string
741
     */
742 1
    public function __toString()
743
    {
744 1
        return $this->toJson();
745
    }
746
}
747