Completed
Push — master ( b018a7...dac3d0 )
by Dan
02:17
created

MessageFactory::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
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 View Code Duplication
        if (isset($data['subtype']) && $data['subtype'] === 'message_changed' && 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...
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 View Code Duplication
        if (isset($data['subtype']) && $data['subtype'] === 'message_changed' && 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...
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();
1 ignored issue
show
Bug introduced by
Consider using $channel->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
147
        }
148
149
        return $entity;
150
    }
151
152
    public function formatReadable(string $match, string $readable = '') : string
153
    {
154
        return $readable ?? $match;
155
    }
156
}
157