Skip to content

Commit 1313806

Browse files
committed
Download source improvements
- `DownloadLinkFetcher` API changes. - Supports fetching sha256 hashes from releases.json files. - Download source changes from `windows.php.net` to `downloads.php.net`
1 parent 830df80 commit 1313806

File tree

1 file changed

+85
-25
lines changed

1 file changed

+85
-25
lines changed

src/DownloadLinkFetcher.php

Lines changed: 85 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
<?php
22

33
namespace PHPWatch\PHPCommitBuilder;
4+
45
class DownloadLinkFetcher {
6+
7+
private const string RELEASES_JSON = 'https://downloads.php.net/~windows/releases/releases.json';
8+
private const string RELEASES_QA_JSON = 'https://downloads.php.net/~windows/qa/releases.json';
9+
10+
private ?array $hashes = null;
11+
512
public function getLinksForTag(string $tag): array {
613
$return = [];
714

@@ -11,9 +18,11 @@ public function getLinksForTag(string $tag): array {
1118
foreach ($urls as $type => $links) {
1219
foreach ($links as $link) {
1320
if (isset($urlStatus[$link])) {
21+
$file = basename($link);
1422
$return[$type] = [
1523
'url' => $link,
1624
'size' => $urlStatus[$link],
25+
'sha256' => isset($this->hashes[$file]) ? $this->hashes[$file]['sha256'] : null,
1726
];
1827
}
1928
}
@@ -22,49 +31,96 @@ public function getLinksForTag(string $tag): array {
2231
return $return;
2332
}
2433

25-
private static function determineVCVersion(string $tag): string {
26-
if (preg_match('/^php-7\.2\./', $tag)) {
27-
return 'VC15';
28-
}
29-
if (preg_match('/^php-7\.3\./', $tag)) {
30-
return 'VC15';
34+
private static function inspectTag(string $tag): array {
35+
$info = [
36+
'QA' => false,
37+
'VS' => 'vs17',
38+
'lookupHash' => false,
39+
];
40+
41+
if (preg_match('/^php-[\d.]+0(alpha|beta|rc|RC)\d$/', $tag)) {
42+
$info['QA'] = true;
43+
}
44+
45+
if (preg_match('/^php-7\.2\./', $tag) || preg_match('/^php-7\.3\./', $tag)) {
46+
$info['VS'] = 'VC15';
47+
return $info;
3148
}
49+
3250
if (preg_match('/^php-7\.4\./', $tag)) {
33-
return 'vc15';
51+
$info['VS'] = 'vc15';
52+
return $info;
3453
}
54+
3555
if (preg_match('/^php-8\.[0123]\./', $tag)) {
36-
return 'vs16';
56+
$info['VS'] = 'vs16';
57+
$info['lookupHash'] = true;
58+
return $info;
3759
}
38-
return 'vs17';
60+
61+
return $info;
3962
}
4063

64+
private function ensureReleasesJson(): void {
65+
if ($this->hashes !== null) {
66+
return;
67+
}
68+
69+
$hashes = [];
70+
71+
$this->ingestHashList(self::RELEASES_JSON, $hashes);
72+
$this->ingestHashList(self::RELEASES_QA_JSON, $hashes);
73+
74+
$this->hashes = $hashes;
75+
}
76+
77+
private function ingestHashList(string $url, &$hashes): void {
78+
$releasesJson = file_get_contents(self::RELEASES_JSON);
79+
$releases = json_decode($releasesJson, associative: true, depth: 10, flags: JSON_THROW_ON_ERROR);
80+
81+
foreach ($releases as $version_ => $files) {
82+
foreach ($files as $file) {
83+
if (!isset($file['zip'])) {
84+
continue;
85+
}
86+
87+
if (isset($file['zip']['sha256'])) {
88+
$hashes[$file['zip']['path']]['sha256'] = $file['zip']['sha256'];
89+
}
90+
}
91+
}
92+
}
93+
4194
private function getWindowsLinks(string $tag): array {
4295
$folder = 'releases/archives';
4396
$folder_alt = 'releases';
4497

45-
if (preg_match('/^php-[\d.]+0(alpha|beta|rc|RC)\d$/', $tag)) {
46-
$folder = 'qa/archives';
47-
$folder_alt = 'qa';
48-
}
98+
$info = self::inspectTag($tag);
99+
$vsVersion = $info['VS'];
49100

50-
$vsVersion = self::determineVCVersion($tag);
101+
if ($info['QA']) {
102+
$folder = 'qa/archives';
103+
$folder_alt = 'qa';
104+
}
105+
106+
$this->ensureReleasesJson();
51107

52108
return [
53109
'x64NTS' => [
54-
'https://windows.php.net/downloads/' . $folder . '/' . $tag . '-nts-Win32-'. $vsVersion .'-x64.zip',
55-
'https://windows.php.net/downloads/' . $folder_alt . '/' . $tag . '-nts-Win32-'. $vsVersion .'-x64.zip',
110+
'https://downloads.php.net/~windows/' . $folder . '/' . $tag . '-nts-Win32-'. $vsVersion .'-x64.zip',
111+
'https://downloads.php.net/~windows/' . $folder_alt . '/' . $tag . '-nts-Win32-'. $vsVersion .'-x64.zip',
56112
],
57113
'x64TS' => [
58-
'https://windows.php.net/downloads/' . $folder . '/' . $tag . '-Win32-' . $vsVersion . '-x64.zip',
59-
'https://windows.php.net/downloads/' . $folder_alt . '/' . $tag . '-Win32-' . $vsVersion . '-x64.zip',
114+
'https://downloads.php.net/~windows/' . $folder . '/' . $tag . '-Win32-' . $vsVersion . '-x64.zip',
115+
'https://downloads.php.net/~windows/' . $folder_alt . '/' . $tag . '-Win32-' . $vsVersion . '-x64.zip',
60116
],
61117
'x86NTS' => [
62-
'https://windows.php.net/downloads/' . $folder . '/' . $tag . '-nts-Win32-' . $vsVersion . '-x86.zip',
63-
'https://windows.php.net/downloads/' . $folder_alt . '/' . $tag . '-nts-Win32-' . $vsVersion . '-x86.zip',
118+
'https://downloads.php.net/~windows/' . $folder . '/' . $tag . '-nts-Win32-' . $vsVersion . '-x86.zip',
119+
'https://downloads.php.net/~windows/' . $folder_alt . '/' . $tag . '-nts-Win32-' . $vsVersion . '-x86.zip',
64120
],
65121
'x86TS' => [
66-
'https://windows.php.net/downloads/' . $folder . '/' . $tag . '-Win32-' . $vsVersion . '-x86.zip',
67-
'https://windows.php.net/downloads/' . $folder_alt . '/' . $tag . '-Win32-' . $vsVersion . '-x86.zip',
122+
'https://downloads.php.net/~windows/' . $folder . '/' . $tag . '-Win32-' . $vsVersion . '-x86.zip',
123+
'https://downloads.php.net/~windows/' . $folder_alt . '/' . $tag . '-Win32-' . $vsVersion . '-x86.zip',
68124
],
69125
];
70126
}
@@ -96,6 +152,10 @@ private function getMultiUrlStatus(array $urlsets): array {
96152

97153
CURLOPT_NOBODY => true,
98154
CURLOPT_HEADER => true,
155+
156+
CURLOPT_HTTPHEADER => [
157+
'Range: bytes=-1',
158+
],
99159
]);
100160

101161
curl_multi_add_handle($cm, $ch);
@@ -111,7 +171,7 @@ private function getMultiUrlStatus(array $urlsets): array {
111171

112172
foreach ($handlers as $urls) {
113173
foreach ($urls as $url) {
114-
if (curl_getinfo($url, CURLINFO_HTTP_CODE) === 200) {
174+
if (curl_getinfo($url, CURLINFO_HTTP_CODE) === 206) {
115175
$completedUrls[curl_getinfo($url, CURLINFO_EFFECTIVE_URL)] = curl_multi_getcontent($url);
116176
}
117177
curl_multi_remove_handle($cm, $url);
@@ -121,12 +181,12 @@ private function getMultiUrlStatus(array $urlsets): array {
121181
curl_multi_close($cm);
122182

123183
foreach ($completedUrls as &$headers) {
124-
preg_match('/content-length: (?<size>\d+)\D/i', $headers, $matches);
184+
preg_match('/content-range: bytes \d+-\d+\/(?<size>\d+)\b/i', $headers, $matches);
125185
if (!empty($matches['size'])) {
126186
$headers = $matches['size'];
127187
}
128188
else {
129-
throw new \LogicException('Content-length not matched');
189+
throw new \LogicException('Content-range not matched');
130190
}
131191
}
132192

0 commit comments

Comments
 (0)