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

eliashaeussler / composer-package-url-generator / 12717909903

10 Jan 2025 10:04PM UTC coverage: 92.453% (+1.0%) from 91.453%
12717909903

push

github

web-flow
Merge pull request #17 from eliashaeussler/feature/gitlab-url-generator

40 of 42 new or added lines in 2 files covered. (95.24%)

147 of 159 relevant lines covered (92.45%)

3.21 hits per line

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

95.12
/src/Url/Generator/GitLabUrlGenerator.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of the Composer package "eliashaeussler/composer-package-url-generator".
7
 *
8
 * Copyright (C) 2023-2025 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\ComposerPackageUrlGenerator\Url\Generator;
25

26
use Composer\Composer;
27
use Composer\Package;
28
use EliasHaeussler\ComposerPackageUrlGenerator\Exception;
29
use EliasHaeussler\ComposerPackageUrlGenerator\Helper;
30
use GuzzleHttp\Psr7;
31
use Psr\Http\Message;
32

33
use function preg_match;
34
use function sprintf;
35
use function str_contains;
36
use function str_replace;
37
use function str_starts_with;
38

39
/**
40
 * GitLabUrlGenerator.
41
 *
42
 * @author Elias Häußler <elias@haeussler.dev>
43
 * @license GPL-3.0-or-later
44
 */
45
final class GitLabUrlGenerator implements UrlGenerator
46
{
47
    /**
48
     * @var string[]
49
     */
50
    private readonly array $domains;
51

52
    public function __construct(Composer $composer)
13✔
53
    {
54
        /* @phpstan-ignore assign.propertyType */
55
        $this->domains = $composer->getPackage()->getConfig()['gitlab-domains'] ?? ['gitlab.com'];
13✔
56
    }
57

58
    /**
59
     * @throws Exception\NoSourceUrlAvailable
60
     * @throws Exception\UrlIsMalformed
61
     */
62
    public function generateSourceUrl(Package\PackageInterface $package): Message\UriInterface
7✔
63
    {
64
        $candidates = [];
7✔
65
        $candidates += $package->getSourceUrls();
7✔
66
        $candidates += $package->getDistUrls();
7✔
67

68
        foreach ($candidates as $candidate) {
7✔
69
            $sourceUrl = Helper\UrlHelper::normalizeUrl($candidate);
6✔
70

71
            if (str_starts_with($sourceUrl->getPath(), '/api/v4/')) {
6✔
72
                $sourceUrl = $this->extractSourceUrlFromApiUrl($sourceUrl);
4✔
73
            }
74

75
            if (null !== $sourceUrl) {
6✔
76
                return $sourceUrl;
4✔
77
            }
78
        }
79

80
        throw new Exception\NoSourceUrlAvailable($package->getName());
3✔
81
    }
82

83
    /**
84
     * @throws Exception\UrlIsMalformed
85
     */
86
    public function generateHomepageUrl(Package\PackageInterface $package): ?Message\UriInterface
4✔
87
    {
88
        if ($package instanceof Package\CompletePackageInterface && null !== $package->getHomepage()) {
4✔
89
            return Helper\UrlHelper::normalizeUrl($package->getHomepage());
1✔
90
        }
91

92
        try {
93
            return $this->generateSourceUrl($package);
3✔
94
        } catch (Exception\NoSourceUrlAvailable) {
1✔
95
            return null;
1✔
96
        }
97
    }
98

99
    public function supports(Package\PackageInterface $package): bool
5✔
100
    {
101
        $candidates = [];
5✔
102
        $candidates += $package->getSourceUrls();
5✔
103
        $candidates += $package->getDistUrls();
5✔
104

105
        foreach ($candidates as $candidate) {
5✔
106
            foreach ($this->domains as $domain) {
4✔
107
                if (str_contains($candidate, $domain)) {
4✔
108
                    return true;
4✔
109
                }
110
            }
111
        }
112

113
        return false;
1✔
114
    }
115

NEW
116
    public static function getPriority(): int
×
117
    {
NEW
118
        return 100;
×
119
    }
120

121
    private function extractSourceUrlFromApiUrl(Message\UriInterface $apiUrl): ?Message\UriInterface
4✔
122
    {
123
        $path = $apiUrl->getPath();
4✔
124

125
        if (1 !== preg_match('#/api/v4/projects/(?<namespace>[^/]+)/repository/archive\.zip$#', $path, $matches)) {
4✔
126
            return null;
2✔
127
        }
128

129
        // https://gitlab.com/api/v4/projects/foo%2Fbaz/repository/archive.zip?sha=b9a16c6d0bc4f591d631a6ceb3c320859ce811c2 => https://gitlab.com/foo/baz
130
        return new Psr7\Uri(
2✔
131
            sprintf(
2✔
132
                'https://%s/%s',
2✔
133
                $apiUrl->getHost(),
2✔
134
                str_replace('%2F', '/', $matches['namespace']),
2✔
135
            ),
2✔
136
        );
2✔
137
    }
138
}
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