• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eliashaeussler / composer-update-check / 10285821446

07 Aug 2024 02:02PM UTC coverage: 25.504%. First build
10285821446

Pull #130

github

web-flow
Merge ed00778d6 into 7d4f7bd74
Pull Request #130: [!!!][FEATURE] Modernize plugin

328 of 1362 new or added lines in 47 files covered. (24.08%)

354 of 1388 relevant lines covered (25.5%)

1.34 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Entity/Report/MattermostReport.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of the Composer package "eliashaeussler/composer-update-check".
7
 *
8
 * Copyright (C) 2020-2024 Elias Häußler <elias@haeussler.dev>
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation, either version 3 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22
 */
23

24
namespace EliasHaeussler\ComposerUpdateCheck\Entity\Report;
25

26
use EliasHaeussler\ComposerUpdateCheck\Entity;
27
use JsonSerializable;
28

29
use function count;
30
use function implode;
31
use function sprintf;
32
use function str_repeat;
33

34
/**
35
 * MattermostReport.
36
 *
37
 * @author Elias Häußler <elias@haeussler.dev>
38
 * @license GPL-3.0-or-later
39
 */
40
final class MattermostReport implements JsonSerializable
41
{
42
    /**
43
     * @param list<Dto\MattermostAttachment> $attachments
44
     */
NEW
45
    private function __construct(
×
46
        public readonly string $channel,
47
        public readonly string $text,
48
        public readonly array $attachments,
49
        public readonly ?string $iconEmoji = null,
50
        public readonly ?string $username = null,
NEW
51
    ) {}
×
52

NEW
53
    public static function create(
×
54
        string $channel,
55
        ?string $username,
56
        Entity\Result\UpdateCheckResult $result,
57
        string $rootPackageName = null,
58
    ): self {
NEW
59
        return new self(
×
NEW
60
            $channel,
×
NEW
61
            self::createText($result, $rootPackageName),
×
NEW
62
            self::createAttachments($result),
×
NEW
63
            ':rotating_light:',
×
NEW
64
            $username,
×
NEW
65
        );
×
66
    }
67

NEW
68
    private static function createText(Entity\Result\UpdateCheckResult $result, string $rootPackageName = null): string
×
69
    {
NEW
70
        $numberOfOutdatedPackages = count($result->getOutdatedPackages());
×
NEW
71
        $numberOfInsecurePackages = count($result->getInsecureOutdatedPackages());
×
NEW
72
        $textParts = [];
×
73

74
        // Outdated packages header
NEW
75
        $textParts[] = sprintf(
×
NEW
76
            '#### %d outdated%s package%s',
×
NEW
77
            $numberOfOutdatedPackages,
×
NEW
78
            $numberOfInsecurePackages > 0 ? sprintf(' (%d insecure)', $numberOfInsecurePackages) : '',
×
NEW
79
            1 !== $numberOfOutdatedPackages ? 's' : '',
×
NEW
80
        );
×
81

82
        // Outdated packages table
NEW
83
        $textParts[] = self::renderOutdatedPackagesTable($result, $rootPackageName);
×
84

NEW
85
        return implode(PHP_EOL, $textParts);
×
86
    }
87

88
    /**
89
     * @return list<Dto\MattermostAttachment>
90
     */
NEW
91
    private static function createAttachments(Entity\Result\UpdateCheckResult $result): array
×
92
    {
NEW
93
        $attachments = [];
×
94

NEW
95
        foreach ($result->getSecurityAdvisories() as $securityAdvisory) {
×
NEW
96
            $attachments[] = new Dto\MattermostAttachment(
×
NEW
97
                self::getColorForSeverityLevel($securityAdvisory->getSeverity()),
×
NEW
98
                self::renderSecurityAdvisoryTable($securityAdvisory),
×
NEW
99
            );
×
100
        }
101

NEW
102
        return $attachments;
×
103
    }
104

NEW
105
    private static function renderOutdatedPackagesTable(
×
106
        Entity\Result\UpdateCheckResult $result,
107
        string $rootPackageName = null,
108
    ): string {
NEW
109
        $numberOfExcludedPackages = count($result->getExcludedPackages());
×
NEW
110
        $hasInsecureOutdatedPackages = $result->hasInsecureOutdatedPackages();
×
NEW
111
        $textParts = [];
×
112

NEW
113
        if (null !== $rootPackageName) {
×
NEW
114
            $textParts[] = sprintf('##### %s', $rootPackageName);
×
115
        }
116

NEW
117
        $headers = [
×
NEW
118
            'Package',
×
NEW
119
            'Current version',
×
NEW
120
            'New version',
×
NEW
121
        ];
×
122

NEW
123
        if ($hasInsecureOutdatedPackages) {
×
NEW
124
            $headers[] = 'Severity';
×
125
        }
126

NEW
127
        $textParts[] = '|'.implode(' | ', $headers).'|';
×
NEW
128
        $textParts[] = str_repeat('|:--- ', count($headers)).'|';
×
129

NEW
130
        foreach ($result->getOutdatedPackages() as $outdatedPackage) {
×
NEW
131
            $severityLevel = $outdatedPackage->getHighestSeverityLevel();
×
132

NEW
133
            $row = sprintf(
×
NEW
134
                '| [%s](%s) | %s | **%s** |',
×
NEW
135
                $outdatedPackage->getName(),
×
NEW
136
                $outdatedPackage->getProviderLink(),
×
NEW
137
                $outdatedPackage->getOutdatedVersion(),
×
NEW
138
                $outdatedPackage->getNewVersion(),
×
NEW
139
            );
×
140

NEW
141
            if (null !== $severityLevel) {
×
NEW
142
                $row .= sprintf(
×
NEW
143
                    ' %s `%s` |',
×
NEW
144
                    self::getEmojiForSeverityLevel($severityLevel),
×
NEW
145
                    $severityLevel->value,
×
NEW
146
                );
×
NEW
147
            } elseif ($hasInsecureOutdatedPackages) {
×
NEW
148
                $row .= ' |';
×
149
            }
150

NEW
151
            $textParts[] = $row;
×
152
        }
153

NEW
154
        if ($numberOfExcludedPackages > 0) {
×
NEW
155
            $textParts[] = sprintf(
×
NEW
156
                '_%d package%s excluded from update check._',
×
NEW
157
                $numberOfExcludedPackages,
×
NEW
158
                1 !== $numberOfExcludedPackages ? 's were' : ' was',
×
NEW
159
            );
×
160
        }
161

NEW
162
        return implode(PHP_EOL, $textParts);
×
163
    }
164

NEW
165
    private static function renderSecurityAdvisoryTable(Entity\Security\SecurityAdvisory $securityAdvisory): string
×
166
    {
NEW
167
        $textParts = [
×
NEW
168
            sprintf('###### %s', $securityAdvisory->getSanitizedTitle()),
×
NEW
169
            sprintf('* Package: `%s`', $securityAdvisory->getPackageName()),
×
NEW
170
            sprintf('* Reported at: `%s`', $securityAdvisory->getReportedAt()->format('Y-m-d')),
×
NEW
171
        ];
×
172

NEW
173
        if (null !== $securityAdvisory->getCVE()) {
×
NEW
174
            $textParts[] = sprintf('* CVE: `%s`', $securityAdvisory->getCVE());
×
175
        }
176

NEW
177
        if (null !== $securityAdvisory->getLink()) {
×
NEW
178
            $textParts[] = sprintf('[Read more](%s)', $securityAdvisory->getLink());
×
179
        }
180

NEW
181
        return implode(PHP_EOL, $textParts);
×
182
    }
183

NEW
184
    private static function getColorForSeverityLevel(Entity\Security\SeverityLevel $severityLevel): string
×
185
    {
NEW
186
        return match ($severityLevel) {
×
NEW
187
            Entity\Security\SeverityLevel::Low => '#EEEEEE',
×
NEW
188
            Entity\Security\SeverityLevel::Medium => '#FFD966',
×
NEW
189
            Entity\Security\SeverityLevel::High => '#F67C41',
×
NEW
190
            Entity\Security\SeverityLevel::Critical => '#EE0000',
×
NEW
191
        };
×
192
    }
193

NEW
194
    private static function getEmojiForSeverityLevel(Entity\Security\SeverityLevel $severityLevel): string
×
195
    {
NEW
196
        return match ($severityLevel) {
×
NEW
197
            Entity\Security\SeverityLevel::Low => ':white_circle:',
×
NEW
198
            Entity\Security\SeverityLevel::Medium => ':large_yellow_circle:',
×
NEW
199
            Entity\Security\SeverityLevel::High => ':large_orange_circle:',
×
NEW
200
            Entity\Security\SeverityLevel::Critical => ':red_circle:',
×
NEW
201
        };
×
202
    }
203

204
    /**
205
     * @return array{
206
     *     channel: string,
207
     *     text: string,
208
     *     attachments: list<Dto\MattermostAttachment>,
209
     *     username?: string,
210
     * }
211
     */
NEW
212
    public function jsonSerialize(): array
×
213
    {
NEW
214
        $json = [
×
NEW
215
            'channel' => $this->channel,
×
NEW
216
            'text' => $this->text,
×
NEW
217
            'attachments' => $this->attachments,
×
NEW
218
            'icon_emoji' => $this->iconEmoji,
×
NEW
219
        ];
×
220

NEW
221
        if (null !== $this->username) {
×
NEW
222
            $json['username'] = $this->username;
×
223
        }
224

NEW
225
        return $json;
×
226
    }
227
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc