MessageFactory::formatAttachmentsText()   A
last analyzed

Complexity

Conditions 5
Paths 2

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

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