Completed
Push — master ( dc345d...e5d792 )
by Dan
02:10
created

MessageFactory::getUserId()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 3
Ratio 25 %

Importance

Changes 0
Metric Value
dl 3
loc 12
rs 9.2
c 0
b 0
f 0
cc 4
eloc 6
nc 3
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 View Code Duplication
        if ($this->isMessageChanged($data) && isset($data['message']['text'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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): bool
162
    {
163
        return isset($data['subtype']) && $data['subtype'] === 'message_changed';
164
    }
165
166
    protected function getUserId(array $data)
167
    {
168 View Code Duplication
        if ($this->isMessageChanged($data) && isset($data['message']['user'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
169
            return $data['message']['user'];
170
        }
171
172
        if (isset($data['user'])) {
173
            return $data['user'];
174
        }
175
176
        return null;
177
    }
178
}
179