Completed
Push — master ( 1b605f...95b7c3 )
by Dan
06:00
created

MessageFactory::create()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 1
1
<?php
2
3
namespace Nopolabs\Yabot\Message;
4
5
use Nopolabs\Yabot\Helpers\SlackTrait;
6
use Nopolabs\Yabot\Slack\Client;
7
8
class MessageFactory
9
{
10
    use SlackTrait;
11
12
    public function __construct(Client $slackClient)
13
    {
14
        $this->setSlack($slackClient);
15
    }
16
17
    public function create(array $data) : Message
18
    {
19
        $formattedText = $this->assembleFormattedText($data);
20
        $user = $this->getUser($data);
21
        $channel = $this->getChannel($data);
22
23
        return new Message($this->getSlack(), $data, $formattedText, $user, $channel);
0 ignored issues
show
Bug introduced by
It seems like $channel defined by $this->getChannel($data) on line 21 can be null; however, Nopolabs\Yabot\Message\Message::__construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
24
    }
25
26
    public function getUser(array $data)
27
    {
28
        if (isset($data['subtype']) && $data['subtype'] === 'message_changed' && isset($data['message']['user'])) {
29
            $userId = $data['message']['user'];
30
        } else {
31
            $userId = $data['user'] ?? null;
32
        }
33
34
        return $userId ? $this->getUserById($userId) : null;
35
    }
36
37
    public function getChannel(array $data)
38
    {
39
        return $this->getChannelById($data['channel']);
40
    }
41
42
    public function assembleFormattedText(array $data) : string
43
    {
44
        if (isset($data['subtype']) && $data['subtype'] === 'message_changed' && isset($data['message']['text'])) {
45
            $formatted = [$this->formatText($data['message']['text'])];
46
        } elseif (isset($data['text'])) {
47
            $formatted = [$this->formatText($data['text'])];
48
        } else {
49
            $formatted = [];
50
        }
51
52
        if (isset($data['attachments'])) {
53
            foreach ($data['attachments'] as $attachment) {
54
                if (isset($attachment['fallback'])) {
55
                    $formatted[] = $this->formatText($attachment['fallback']);
56
                }
57
            }
58
        }
59
60
        return trim(implode("\n", array_filter($formatted)));
61
    }
62
63
    public function formatText(string $text) : string
64
    {
65
        $pattern = '/<([^>]*)>/';
66
67
        preg_match_all($pattern, $text, $matches);
68
69
        $split = preg_split($pattern, $text);
70
71
        $index = 0;
72
        $formatted = [];
73
74
        foreach ($matches[1] as $match) {
75
            $formatted[] = $split[$index++];
76
            $formatted[] = $this->formatEntity($match);
77
        }
78
79
        if ($index < count($split)) {
80
            $formatted[] = $split[$index];
81
        }
82
83
        return trim(implode('', $formatted));
84
    }
85
86
    public function formatEntity(string $entity) : string
87
    {
88
        $pipe = strrpos($entity, '|');
89
        $readable = ($pipe !== false) ? substr($entity, $pipe + 1) : false;
90
91
        if ($entity && $entity[0] === '@') {
92
            return $this->formatUser($entity, $readable);
93
        }
94
        if ($entity && $entity[0] === '#') {
95
            return $this->formatChannel($entity, $readable);
96
        }
97
98
        return $this->formatReadable($entity, $readable);
99
    }
100
101
    public function formatUser(string $entity, $readable) : string
102
    {
103
        if ($readable) {
104
            return $readable;
105
        }
106
107
        $userId = substr($entity, 1);
108
        if ($user = $this->getUserById($userId)) {
109
            return '@'.$user->getUsername();
110
        }
111
112
        return $entity;
113
    }
114
115
    public function formatChannel(string $entity, $readable) : string
116
    {
117
        if ($readable) {
118
            return $readable;
119
        }
120
121
        $channelId = substr($entity, 1);
122
        if ($channel = $this->getChannelById($channelId)) {
123
            return '#'.$channel->getName();
124
        }
125
126
        return $entity;
127
    }
128
129
    public function formatReadable(string $match, $readable) : string
130
    {
131
        return $readable ?? $match;
132
    }
133
}
134