diff --git a/.gitignore b/.gitignore index 5fa5cd36ef..68e6dab8a5 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ backend/mirror.gif backend/mirror.png backend/mirror.jpg backend/GeoIP.dat +include/download-instructions/releases.json node_modules/ /test-results/ /playwright-report/ diff --git a/include/download-instructions/windows-downloads.php b/include/download-instructions/windows-downloads.php index d8a86114e3..ea014e2d30 100644 --- a/include/download-instructions/windows-downloads.php +++ b/include/download-instructions/windows-downloads.php @@ -1,3 +1,131 @@ -

-You can find the downloads for Windows on the dedicated downloads page. -

+ [ + 'header' => "User-Agent: web-php/1.1", + 'timeout' => 5, + ], + 'ssl' => [ + 'allow_self_signed' => true, + 'verify_peer_name' => false, + ], + ]); + $json = @file_get_contents($releasesUrl, false, $context); + if ($json === false || $json === null) { + $json = @file_get_contents($fallbackReleasesUrl, false, $context); + } + if ($json !== false && $json !== null) { + $tmp = $cacheFile . '.tmp'; + if (@file_put_contents($tmp, $json) !== false) { + @rename($tmp, $cacheFile); + } + } +} + +$dataStr = @file_get_contents($cacheFile); +$releases = $dataStr ? json_decode($dataStr ?? $json, true) : null; + +if (!is_array($releases)) { + echo '

Windows release index is temporarily unavailable.

'; + if (file_exists($cacheFile)) { + @unlink($cacheFile); + } + return; +} + +if (!isset($releases[$version]) || !is_array($releases[$version])) { + echo '

No Windows builds found for PHP ' . htmlspecialchars($version) . '.

'; + return; +} + +$verBlock = $releases[$version]; +$fullVersion = isset($verBlock['version']) ? $verBlock['version'] : $version; + +$baseDownloads = 'https://downloads.php.net/~windows/releases/'; + +function ws_build_label(string $k, array $entry): string { + $tool = 'VS'; + if (strpos($k, 'vs17') !== false) { $tool .= '17'; } + elseif (strpos($k, 'vs16') !== false) { $tool .= '16'; } + elseif (strpos($k, 'vc15') !== false) { $tool = 'VC15'; } + + $arch = (strpos($k, 'x64') !== false) ? 'x64' : ((strpos($k, 'x86') !== false) ? 'x86' : ''); + $ts = (strpos($k, 'nts') !== false) ? 'Non Thread Safe' : 'Thread Safe'; + if (strncmp($k, 'nts-', 4) === 0) { + $ts = 'Non Thread Safe'; + } elseif (strncmp($k, 'ts-', 3) === 0) { + $ts = 'Thread Safe'; + } + + $mtime = isset($entry['mtime']) ? strtotime($entry['mtime']) : 0; + $mt = $mtime ? gmdate('Y-M-d H:i:s', $mtime) : ''; + return trim(($tool ? $tool . ' ' : '') . ($arch ? $arch . ' ' : '') . $ts . ($mt ? ' ' . $mt . ' UTC' : '')); +} + +echo '

PHP ' . htmlspecialchars($version) . ' (' . $fullVersion . ')

'; + +if (!empty($verBlock['source']['path'])) { + echo '

Download source code ' . $verBlock['source']['size'] ?? '' . '

'; +} +if (!empty($verBlock['test_pack']['path'])) { + echo '

Download tests package (phpt) ' . $verBlock['test_pack']['size'] ?? '' . '

'; +} + +$buckets = [ + 'nts-x64' => [], + 'ts-x64' => [], + 'nts-x86' => [], + 'ts-x86' => [], +]; + +$package_names = [ + 'zip' => 'Zip', + 'debug_pack' => 'Debug Pack', + 'devel_pack' => 'Development package (SDK to develop PHP extensions)', +]; + +foreach ($verBlock as $k => $entry) { + if (!is_array($entry)) { continue; } + if (in_array($k, ['version', 'source', 'test_pack'], true)) { continue; } + + $isNts = (strncmp($k, 'nts-', 4) === 0) || (strpos($k, 'nts') !== false); + $arch = (strpos($k, 'x64') !== false) ? 'x64' : ((strpos($k, 'x86') !== false) ? 'x86' : ''); + $bucketKey = ($isNts ? 'nts' : 'ts') . '-' . ($arch !== '' ? $arch : 'other'); + if (!isset($buckets[$bucketKey])) { $bucketKey = 'other'; } + $buckets[$bucketKey][] = [$k, $entry]; +} + +foreach (['nts-x64', 'ts-x64', 'nts-x86', 'ts-x86'] as $bk) { + foreach ($buckets[$bk] as [$k, $entry]) { + $label = ws_build_label($k, $entry); + if ($label === '') { continue; } + + echo '
'; + echo '

' . $label . '

'; + + foreach(['zip', 'debug_pack', 'devel_pack'] as $type) { + if (!empty($entry[$type]['path'])) { + $p = $entry[$type]['path']; + echo '

' . $package_names[$type] . ' ' . $entry[$type]['size'] . '
'; + echo 'sha256: ' . $entry[$type]['sha256'] ?? '' . '

'; + } + } + + echo '
'; + } +} + +?> diff --git a/include/version.inc b/include/version.inc index 75d9a16f91..75a17d27bb 100644 --- a/include/version.inc +++ b/include/version.inc @@ -147,7 +147,7 @@ function show_source_releases()
  • - + Windows downloads
  • diff --git a/styles/code-syntax.css b/styles/code-syntax.css index 26dfdbf332..0948c34b35 100644 --- a/styles/code-syntax.css +++ b/styles/code-syntax.css @@ -63,3 +63,28 @@ button.copy-to-clipboard-button:hover { border-color: var(--dark-magenta-color) !important; } +.win-build { + background: rgba(39, 40, 44, 0.05); + margin: 20px 0; + padding: 20px 20px 10px 20px; + border-top: 4px solid var(--dark-blue-color, #4F5B93); +} + +.win-build h4 { + line-height: 1.5rem; + margin-bottom: 0; +} + +.instructions .size { + background: #dcdcdc; + border-radius: 6px; + padding: 3px 7px; + font-size: 0.8rem; + font-weight: 600; +} + +.instructions .time { + color: #555; + font-size: 0.8rem; + display: block; +}