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

eliashaeussler / composer-package-url-generator / 12597440321

03 Jan 2025 12:07PM UTC coverage: 64.957% (+13.8%) from 51.19%
12597440321

Pull #13

github

web-flow
Merge 1a6786d46 into 2ffa8dcfd
Pull Request #13: [FEATURE] Provide GitHub URL generator

31 of 33 new or added lines in 2 files covered. (93.94%)

76 of 117 relevant lines covered (64.96%)

2.37 hits per line

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

93.75
/src/Url/Generator/GitHubUrlGenerator.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\Package;
27
use EliasHaeussler\ComposerPackageUrlGenerator\Exception;
28
use EliasHaeussler\ComposerPackageUrlGenerator\Helper;
29
use GuzzleHttp\Psr7;
30
use Psr\Http\Message;
31

32
use function preg_match;
33
use function sprintf;
34
use function str_contains;
35

36
/**
37
 * GitHubUrlGenerator.
38
 *
39
 * @author Elias Häußler <elias@haeussler.dev>
40
 * @license GPL-3.0-or-later
41
 */
42
final class GitHubUrlGenerator implements UrlGenerator
43
{
44
    public function generateSourceUrl(Package\PackageInterface $package): Message\UriInterface
7✔
45
    {
46
        $candidates = [];
7✔
47
        $candidates += $package->getSourceUrls();
7✔
48
        $candidates += $package->getDistUrls();
7✔
49

50
        foreach ($candidates as $candidate) {
7✔
51
            $sourceUrl = Helper\UrlHelper::normalizeUrl($candidate);
6✔
52

53
            if ('api.github.com' === $sourceUrl->getHost()) {
6✔
54
                $sourceUrl = $this->extractSourceUrlFromApiUrl($sourceUrl);
4✔
55
            }
56

57
            if (null !== $sourceUrl) {
6✔
58
                return $sourceUrl;
4✔
59
            }
60
        }
61

62
        throw new Exception\NoSourceUrlAvailable($package->getName());
3✔
63
    }
64

65
    public function generateHomepageUrl(Package\PackageInterface $package): ?Message\UriInterface
4✔
66
    {
67
        if ($package instanceof Package\CompletePackageInterface && null !== $package->getHomepage()) {
4✔
68
            return Helper\UrlHelper::normalizeUrl($package->getHomepage());
1✔
69
        }
70

71
        try {
72
            return $this->generateSourceUrl($package);
3✔
73
        } catch (Exception\NoSourceUrlAvailable) {
1✔
74
            return null;
1✔
75
        }
76
    }
77

78
    public function supports(Package\PackageInterface $package): bool
3✔
79
    {
80
        $candidates = [];
3✔
81
        $candidates += $package->getSourceUrls();
3✔
82
        $candidates += $package->getDistUrls();
3✔
83

84
        foreach ($candidates as $candidate) {
3✔
85
            if (str_contains($candidate, 'github.com')) {
2✔
86
                return true;
2✔
87
            }
88
        }
89

90
        return false;
1✔
91
    }
92

NEW
93
    public static function getPriority(): int
×
94
    {
NEW
95
        return 0;
×
96
    }
97

98
    private function extractSourceUrlFromApiUrl(Message\UriInterface $apiUrl): ?Message\UriInterface
4✔
99
    {
100
        $path = $apiUrl->getPath();
4✔
101

102
        if (1 !== preg_match('#/repos/(?<user>[^/]+)/(?<repo>[^/]+)/zipball/.+#', $path, $matches)) {
4✔
103
            return null;
2✔
104
        }
105

106
        // https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201 => https://github.com/guzzle/psr7
107
        return new Psr7\Uri(sprintf('https://github.com/%s/%s', $matches['user'], $matches['repo']));
2✔
108
    }
109
}
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