Passed
Push — develop ( d608c2...fea4fb )
by nguereza
01:49
created

WebHook::getCommitFilesChangeMessage()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 5
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 11
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Quantum\Hub;
6
7
use Platine\Config\Config;
8
use Platine\Http\ServerRequest;
9
use Platine\Http\ServerRequestInterface;
10
use Platine\Stdlib\Helper\Arr;
11
use Platine\Stdlib\Helper\Json;
12
use Platine\Stdlib\Helper\Str;
13
use Quantum\Hub\Entity\Commit;
14
use Quantum\Hub\Entity\Repository;
15
use Quantum\Hub\Entity\Sender;
16
17
/**
18
 * @class WebHook
19
 * @package Quantum\Hub
20
 * @template T
21
 */
22
class WebHook
23
{
24
    /**
25
     * The request instance to use
26
     * @var ServerRequestInterface
27
     */
28
    protected ServerRequestInterface $request;
29
30
    /**
31
     * The payload data
32
     * @var array<string, mixed>
33
     */
34
    protected array $payload = [];
35
36
    /**
37
     * Create new instance
38
     * @param Config<T> $config
39
     * @param ServerRequestInterface|null $request
40
     */
41
    public function __construct(
42
        protected Config $config,
43
        ?ServerRequestInterface $request = null,
44
    ) {
45
        if ($request === null) {
46
            $this->request = ServerRequest::createFromGlobals();
47
        }
48
    }
49
50
51
    /**
52
     * Handle the request
53
     * @return void
54
     */
55
    public function handle(): void
56
    {
57
        $this->processPayload();
58
59
        $repository = $this->getRepository();
60
        $commit = $this->getCommit();
61
        $disabledRepos = $this->getDisabledRepositories();
62
        if (
63
            $this->getEvent() !== 'push' ||
64
            $commit === null ||
65
            in_array(
66
                $repository->getFullName(),
67
                $disabledRepos
68
            )
69
        ) {
70
            return;
71
        }
72
73
        $message = $this->getMessageContent($commit, $repository);
74
75
        echo $message;
76
    }
77
78
    /**
79
     * Return the commit branch
80
     * @return string
81
     */
82
    public function getBranch(): string
83
    {
84
        $value = $this->getPayloadValue('ref');
85
        return Arr::last(explode('/', $value));
86
    }
87
88
    /**
89
     * Return the GitHub Event. Currently only push is supported
90
     * @return string
91
     */
92
    public function getEvent(): string
93
    {
94
        return $this->request->getHeaderLine('X-GitHub-Event');
95
    }
96
97
    /**
98
     * Return the value of the payload
99
     * @param string $name
100
     * @param mixed $default
101
     * @return mixed
102
     */
103
    public function getPayloadValue(
104
        string $name,
105
        mixed $default = null
106
    ): mixed {
107
        return Arr::get(
108
            $this->payload,
109
            $name,
110
            $default
111
        );
112
    }
113
114
    /**
115
     * Return the repository info
116
     * @return Repository
117
     */
118
    public function getRepository(): Repository
119
    {
120
        $data = $this->getPayloadValue('repository');
121
122
        return new Repository($data);
123
    }
124
125
     /**
126
     * Return the sender (user who make push) info
127
     * @return Sender
128
     */
129
    public function getSender(): Sender
130
    {
131
        $data = $this->getPayloadValue('sender');
132
133
        return new Sender($data);
134
    }
135
136
    /**
137
     * Return the commit information if have
138
     * @return Commit
139
     */
140
    public function getCommit(): ?Commit
141
    {
142
        $data = $this->getPayloadValue('commits', []);
143
        if (count($data) === 0) {
144
            return null;
145
        }
146
147
        return new Commit($data[0]);
148
    }
149
150
    /**
151
     * Return the list of repository that is disabled
152
     * @return array<string>
153
     */
154
    public function getDisabledRepositories(): array
155
    {
156
        $params = $this->request->getQueryParams();
157
        $repositories = $params['disable_repos'] ?? '';
158
        if (empty($repositories)) {
159
            return [];
160
        }
161
162
        return explode(',', $repositories);
163
    }
164
165
    /**
166
     * Get message content
167
     * @param Commit $commit
168
     * @param Repository $repository
169
     * @return string
170
     */
171
    public function getMessageContent(
172
        Commit $commit,
173
        Repository $repository
174
    ): string {
175
        $sender = $this->getSender();
176
177
        $text = sprintf(
178
            "<a href = \"%s\"><b>@%s</b></a> just push new commit on <a href = \"%s\"><b>%s</b></a>%s%s",
179
            $sender->getHtmlUrl(),
180
            $sender->getLogin(),
181
            $repository->getHtmlUrl(),
182
            $repository->getFullName(),
183
            PHP_EOL,
184
            PHP_EOL
185
        );
186
187
        $text .= $this->buildMessageRow('Description', $commit->getMessage(), 2);
188
        $text .= $this->buildMessageRow('Branch/Tag', $this->getBranch());
189
        $text .= $this->buildMessageRow('Date', $commit->getTimestamp());
190
        $text .= $this->buildMessageRow(
191
            'Commit ID',
192
            sprintf(
193
                '<a href = "%s"><b>%s</b></a>',
194
                $commit->getUrl(),
195
                $commit->getId()
196
            )
197
        );
198
199
        $text .= $this->getCommitFilesChangeMessage($commit->getAdded(), 'added');
200
        $text .= $this->getCommitFilesChangeMessage($commit->getModified(), 'modified');
201
        $text .= $this->getCommitFilesChangeMessage($commit->getRemoved(), 'deleted');
202
203
204
        return $text;
205
    }
206
207
    /**
208
     * Process the payload
209
     * @return void
210
     */
211
    protected function processPayload(): void
212
    {
213
        $body = $this->request->getBody()->getContents();
214
        if (!empty($body)) {
215
            $payload = Json::decode($body, true);
216
217
            $this->payload = $payload;
218
        }
219
    }
220
221
    /**
222
     * Return the commit message files changes (added/removed/modified)
223
     * @param array<string> $files
224
     * @param string $type
225
     * @return string
226
     */
227
    protected function getCommitFilesChangeMessage(array $files, string $type): string
228
    {
229
        if (count($files) === 0) {
230
            return '';
231
        }
232
233
        // Use double quote in order to format EOL
234
        $text = sprintf("%s<b>Files %s:</b>%s", PHP_EOL, $type, PHP_EOL);
235
        $text .= sprintf("- %s %s", implode(PHP_EOL . '- ', $files), PHP_EOL);
236
237
        return $text;
238
    }
239
240
    /**
241
     * Build the message row
242
     * @param string $label
243
     * @param string $value
244
     * @param int $eolCount
245
     * @return string
246
     */
247
    protected function buildMessageRow(
248
        string $label,
249
        string $value,
250
        int $eolCount = 1
251
    ): string {
252
        return sprintf(
253
            "<b>%s:</b> %s%s",
254
            $label,
255
            $value,
256
            Str::repeat(PHP_EOL, $eolCount)
257
        );
258
    }
259
}
260