|
| 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