Completed
Push — master ( 95b7c3...8ed961 )
by Dan
02:21
created

MessageFactory   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 129
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 33
lcom 1
cbo 4
dl 0
loc 129
rs 9.3999
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A create() 0 8 1
B getUser() 0 10 5
A getChannel() 0 4 1
C assembleFormattedText() 0 23 9
A formatText() 0 22 3
B formatEntity() 0 14 6
A formatUser() 0 13 3
A formatChannel() 0 13 3
A formatReadable() 0 4 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['pretext'])) {
55
                    $formatted[] = $this->formatText($attachment['pretext']);
56
                }
57
                if (isset($attachment['fallback'])) {
58
                    $formatted[] = $this->formatText($attachment['fallback']);
59
                }
60
            }
61
        }
62
63
        return trim(implode("\n", array_filter($formatted)));
64
    }
65
66
    public function formatText(string $text) : string
67
    {
68
        $pattern = '/<([^>]*)>/';
69
70
        preg_match_all($pattern, $text, $matches);
71
72
        $split = preg_split($pattern, $text);
73
74
        $index = 0;
75
        $formatted = [];
76
77
        foreach ($matches[1] as $match) {
78
            $formatted[] = $split[$index++];
79
            $formatted[] = $this->formatEntity($match);
80
        }
81
82
        if ($index < count($split)) {
83
            $formatted[] = $split[$index];
84
        }
85
86
        return trim(implode('', $formatted));
87
    }
88
89
    public function formatEntity(string $entity) : string
90
    {
91
        $pipe = strrpos($entity, '|');
92
        $readable = ($pipe !== false) ? substr($entity, $pipe + 1) : false;
93
94
        if ($entity && $entity[0] === '@') {
95
            return $this->formatUser($entity, $readable);
96
        }
97
        if ($entity && $entity[0] === '#') {
98
            return $this->formatChannel($entity, $readable);
99
        }
100
101
        return $this->formatReadable($entity, $readable);
102
    }
103
104
    public function formatUser(string $entity, $readable) : string
105
    {
106
        if ($readable) {
107
            return $readable;
108
        }
109
110
        $userId = substr($entity, 1);
111
        if ($user = $this->getUserById($userId)) {
112
            return '@'.$user->getUsername();
113
        }
114
115
        return $entity;
116
    }
117
118
    public function formatChannel(string $entity, $readable) : string
119
    {
120
        if ($readable) {
121
            return $readable;
122
        }
123
124
        $channelId = substr($entity, 1);
125
        if ($channel = $this->getChannelById($channelId)) {
126
            return '#'.$channel->getName();
127
        }
128
129
        return $entity;
130
    }
131
132
    public function formatReadable(string $match, $readable) : string
133
    {
134
        return $readable ?? $match;
135
    }
136
}
137