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

eliashaeussler / composer-update-check / 12278928207

11 Dec 2024 02:53PM UTC coverage: 20.582%. First build
12278928207

Pull #130

github

web-flow
[TASK] Update composer/composer to v2.8.4 (#172)

| datasource | package           | from  | to    |
| ---------- | ----------------- | ----- | ----- |
| packagist  | composer/composer | 2.8.3 | 2.8.4 |

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Pull Request #130: [!!!][FEATURE] Modernize plugin

356 of 1828 new or added lines in 57 files covered. (19.47%)

382 of 1856 relevant lines covered (20.58%)

1.11 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
    ): self {
NEW
58
        return new self(
×
NEW
59
            $channel,
×
NEW
60
            self::createText($result),
×
NEW
61
            self::createAttachments($result),
×
NEW
62
            ':rotating_light:',
×
NEW
63
            $username,
×
NEW
64
        );
×
65
    }
66

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

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

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

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

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

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

NEW
101
        return $attachments;
×
102
    }
103

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

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

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

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

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

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

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

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

NEW
149
            $textParts[] = $row;
×
150
        }
151

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

NEW
160
        return implode(PHP_EOL, $textParts);
×
161
    }
162

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

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

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

NEW
179
        return implode(PHP_EOL, $textParts);
×
180
    }
181

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

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

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

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

NEW
223
        return $json;
×
224
    }
225
}
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

© 2026 Coveralls, Inc