Completed
Push — master ( 363ea4...173596 )
by Dan
01:37
created

MessageFactory   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 152
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 36
lcom 1
cbo 4
dl 0
loc 152
rs 8.8
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A create() 0 8 1
A getChannel() 0 10 2
A assembleFormattedText() 0 8 1
B formatAttachmentsText() 0 15 5
A formatText() 0 22 3
B formatEntity() 0 14 6
A formatUser() 0 13 3
A formatChannel() 0 13 3
A getUser() 0 8 3
A formatMessageText() 0 12 4
A isMessageChanged() 0 4 2
A formatReadable() 0 4 2
1
<?php
2
3
namespace Nopolabs\Yabot\Message;
4
5
use Exception;
6
use Nopolabs\Yabot\Helpers\SlackTrait;
7
use Nopolabs\Yabot\Slack\Client;
8
use Slack\Channel;
9
10
class MessageFactory
11
{
12
    use SlackTrait;
13
14
    public function __construct(Client $slackClient)
15
    {
16
        $this->setSlack($slackClient);
17
    }
18
19
    public function create(array $data) : Message
20
    {
21
        $formattedText = $this->assembleFormattedText($data);
22
        $user = $this->getUser($data);
23
        $channel = $this->getChannel($data);
24
25
        return new Message($this->getSlack(), $data, $formattedText, $user, $channel);
26
    }
27
28
    public function getUser(array $data)
29
    {
30
        if ($this->isMessageChanged($data) && isset($data['message']['user'])) {
31
            return $this->getUserById($data['message']['user'] ?? null);
32
        }
33
34
        return $this->getUserById($data['user'] ?? null);
35
    }
36
37
    public function getChannel(array $data) : Channel
38
    {
39
        $channel = $this->getChannelById($data['channel']);
40
41
        if ($channel instanceof Channel) {
42
            return $channel;
43
        }
44
45
        throw new Exception('Message data does not have a channel.');
46
    }
47
48
    public function assembleFormattedText(array $data) : string
49
    {
50
        $formatted = [$this->formatMessageText($data)];
51
52
        $formatted = array_merge($formatted, $this->formatAttachmentsText($data));
53
54
        return trim(implode("\n", array_filter($formatted)));
55
    }
56
57
    public function formatMessageText(array $data) : string
58
    {
59
        if ($this->isMessageChanged($data) && isset($data['message']['text'])) {
60
            return $this->formatText($data['message']['text']);
61
        }
62
63
        if (isset($data['text'])) {
64
            return $this->formatText($data['text']);
65
        }
66
67
        return '';
68
    }
69
70
    public function formatAttachmentsText(array $data) : array
71
    {
72
        $formatted = [];
73
        if (isset($data['attachments'])) {
74
            foreach ($data['attachments'] as $attachment) {
75
                if (isset($attachment['pretext'])) {
76
                    $formatted[] = $this->formatText($attachment['pretext']);
77
                }
78
                if (isset($attachment['fallback'])) {
79
                    $formatted[] = $this->formatText($attachment['fallback']);
80
                }
81
            }
82
        }
83
        return $formatted;
84
    }
85
86
    public function formatText(string $text) : string
87
    {
88
        $pattern = '/<([^>]*)>/';
89
90
        preg_match_all($pattern, $text, $matches);
91
92
        $split = preg_split($pattern, $text);
93
94
        $index = 0;
95
        $formatted = [];
96
97
        foreach ($matches[1] as $match) {
98
            $formatted[] = $split[$index++];
99
            $formatted[] = $this->formatEntity($match);
100
        }
101
102
        if ($index < count($split)) {
103
            $formatted[] = $split[$index];
104
        }
105
106
        return trim(implode('', array_filter($formatted)));
107
    }
108
109
    public function formatEntity(string $entity) : string
110
    {
111
        $pipe = strrpos($entity, '|');
112
        $readable = ($pipe !== false) ? substr($entity, $pipe + 1) : '';
113
114
        if ($entity && $entity[0] === '@') {
115
            return $this->formatUser($entity, $readable);
116
        }
117
        if ($entity && $entity[0] === '#') {
118
            return $this->formatChannel($entity, $readable);
119
        }
120
121
        return $this->formatReadable($entity, $readable);
122
    }
123
124
    public function formatUser(string $entity, string $readable = '') : string
125
    {
126
        if ($readable !== '') {
127
            return $readable;
128
        }
129
130
        $userId = substr($entity, 1);
131
        if ($user = $this->getUserById($userId)) {
132
            return '@'.$user->getUsername();
133
        }
134
135
        return $entity;
136
    }
137
138
    public function formatChannel(string $entity, string $readable = '') : string
139
    {
140
        if ($readable !== '') {
141
            return $readable;
142
        }
143
144
        $channelId = substr($entity, 1);
145
        if ($channel = $this->getChannelById($channelId)) {
146
            return '#'.$channel->getName();
147
        }
148
149
        return $entity;
150
    }
151
152
    public function formatReadable(string $match, string $readable = '') : string
153
    {
154
        return empty($readable) ? $match : $readable;
155
    }
156
157
    protected function isMessageChanged(array $data): bool
158
    {
159
        return isset($data['subtype']) && $data['subtype'] === 'message_changed';
160
    }
161
}
162