Skip to content

Commit c3ebfed

Browse files
committed
Add DownloadLinkFetcher
1 parent 0ac7c8e commit c3ebfed

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed

src/DownloadLinkFetcher.php

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?php
2+
3+
namespace PHPWatch\PHPCommitBuilder;
4+
class DownloadLinkFetcher {
5+
public function getLinksForTag(string $tag): array {
6+
$return = [];
7+
8+
$urls = $this->getWindowsLinks($tag);
9+
$urlStatus = $this->getMultiUrlStatus($urls);
10+
11+
foreach ($urls as $type => $links) {
12+
foreach ($links as $link) {
13+
if (isset($urlStatus[$link])) {
14+
$return[$type] = [
15+
'url' => $link,
16+
'size' => $urlStatus[$link],
17+
];
18+
}
19+
}
20+
}
21+
22+
$sourceLinks = $this->getSourceLinks($tag);
23+
$return['zip'] = ['url' => $sourceLinks['zip']];
24+
$return['tar'] = ['url' => $sourceLinks['tar']];
25+
26+
return $return;
27+
}
28+
private function getSourceLinks(string $tag): array {
29+
return [
30+
'zip' => 'https://api.github.com/repos/php/php-src/zipball/refs/tags/' . $tag,
31+
'tar' => 'https://api.github.com/repos/php/php-src/tarball/refs/tags/' . $tag,
32+
];
33+
}
34+
35+
private function getWindowsLinks(string $tag): array {
36+
$folder = 'releases/archives';
37+
$folder_alt = 'releases';
38+
39+
if (preg_match('/^php-[\d.]+0(alpha|beta|rc|RC)\d$/', $tag)) {
40+
$folder = 'qa/archives';
41+
$folder_alt = 'qa';
42+
}
43+
44+
return [
45+
'x64NTS' => [
46+
'https://windows.php.net/downloads/' . $folder . '/' . $tag . '-nts-Win32-vs16-x64.zip',
47+
'https://windows.php.net/downloads/' . $folder_alt . '/' . $tag . '-nts-Win32-vs16-x64.zip',
48+
],
49+
'x64TS' => [
50+
'https://windows.php.net/downloads/' . $folder . '/' . $tag . '-Win32-vs16-x64.zip',
51+
'https://windows.php.net/downloads/' . $folder_alt . '/' . $tag . '-Win32-vs16-x64.zip',
52+
],
53+
'x86NTS' => [
54+
'https://windows.php.net/downloads/' . $folder . '/' . $tag . '-nts-Win32-vs16-x86.zip',
55+
'https://windows.php.net/downloads/' . $folder_alt . '/' . $tag . '-nts-Win32-vs16-x86.zip',
56+
],
57+
'x86TS' => [
58+
'https://windows.php.net/downloads/' . $folder . '/' . $tag . '-Win32-vs16-x86.zip',
59+
'https://windows.php.net/downloads/' . $folder_alt . '/' . $tag . '-Win32-vs16-x86.zip',
60+
],
61+
];
62+
}
63+
64+
private function getMultiUrlStatus(array $urlsets): array {
65+
$cm = curl_multi_init();
66+
$handlers = [];
67+
68+
foreach ($urlsets as $type => $urls) {
69+
foreach ($urls as $i => $url) {
70+
$ch = curl_init($url);
71+
72+
$handlers[$type][$i] = $ch;
73+
74+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
75+
curl_setopt($ch, CURLOPT_HEADER, true);
76+
curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS | CURLPROTO_HTTP);
77+
curl_setopt($ch, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTPS);
78+
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
79+
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
80+
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
81+
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
82+
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
83+
curl_setopt($ch, CURLOPT_ENCODING, '');
84+
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
85+
curl_setopt($ch, CURLOPT_TCP_KEEPALIVE, 1);
86+
curl_setopt($ch, CURLOPT_NOBODY, true);
87+
curl_setopt($ch, CURLOPT_USERAGENT, 'ayesh/curl-fetcher');
88+
89+
curl_multi_add_handle($cm, $ch);
90+
}
91+
}
92+
93+
do {
94+
curl_multi_exec($cm, $running);
95+
curl_multi_select($cm);
96+
} while ($running > 0);
97+
98+
$completedUrls = [];
99+
100+
foreach ($handlers as $type => $urls) {
101+
foreach ($urls as $i => $url) {
102+
if (curl_getinfo($url, CURLINFO_HTTP_CODE) === 200) {
103+
$completedUrls[curl_getinfo($url, CURLINFO_EFFECTIVE_URL)] = curl_multi_getcontent($url);
104+
}
105+
curl_multi_remove_handle($cm, $url);
106+
}
107+
}
108+
109+
curl_multi_close($cm);
110+
111+
foreach ($completedUrls as &$headers) {
112+
preg_match('/content-length: (?<size>\d+)\D/i', $headers, $matches);
113+
if (!empty($matches['size'])) {
114+
$headers = $matches['size'];
115+
}
116+
else {
117+
throw new \LogicException('Content-length not matched');
118+
}
119+
}
120+
121+
return $completedUrls;
122+
}
123+
124+
}

0 commit comments

Comments
 (0)