Skip to content

Commit 8ebe1f7

Browse files
committed
Add windows builds in the downloads page
1 parent c0dda8e commit 8ebe1f7

File tree

3 files changed

+136
-3
lines changed

3 files changed

+136
-3
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ backend/mirror.gif
55
backend/mirror.png
66
backend/mirror.jpg
77
backend/GeoIP.dat
8+
include/download-instructions/releases.json
89
node_modules/
910
/test-results/
1011
/playwright-report/
Lines changed: 125 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,125 @@
1-
<p>
2-
You can find the downloads for Windows on the <a href="https://windows.php.net/download#php-<?= $version; ?>">dedicated downloads page</a>.
3-
</p>
1+
<?php
2+
$cacheFile = (sys_get_temp_dir() ?? __DIR__) . '/releases.json';
3+
$releasesUrl = 'https://downloads.php.net/~windows/releases/releases.json';
4+
$fallbackReleasesUrl = 'https://downloads.internal.php.net/~windows/releases/releases.json';
5+
$maxAge = 3600;
6+
7+
$needFetch = true;
8+
if (file_exists($cacheFile)) {
9+
$mtime = @filemtime($cacheFile) ?: 0;
10+
if (time() - $mtime < $maxAge) {
11+
$needFetch = false;
12+
}
13+
}
14+
15+
if ($needFetch) {
16+
$context = stream_context_create([
17+
'http' => [
18+
'header' => "User-Agent: web-php/1.1",
19+
'timeout' => 5,
20+
],
21+
'ssl' => [
22+
'allow_self_signed' => true,
23+
'verify_peer_name' => false,
24+
],
25+
]);
26+
$json = @file_get_contents($releasesUrl, false, $context);
27+
if ($json === false || $json === null) {
28+
$json = @file_get_contents($fallbackReleasesUrl, false, $context);
29+
}
30+
if ($json !== false && $json !== null) {
31+
$tmp = $cacheFile . '.tmp';
32+
if (@file_put_contents($tmp, $json) !== false) {
33+
@rename($tmp, $cacheFile);
34+
}
35+
}
36+
}
37+
38+
$dataStr = @file_get_contents($cacheFile);
39+
$releases = $dataStr ? json_decode($dataStr ?? $json, true) : null;
40+
41+
if (!is_array($releases)) {
42+
echo '<p>Windows release index is temporarily unavailable.</p>';
43+
if (file_exists($cacheFile)) {
44+
@unlink($cacheFile);
45+
}
46+
return;
47+
}
48+
49+
if (!isset($releases[$version]) || !is_array($releases[$version])) {
50+
echo '<p>No Windows builds found for PHP ' . htmlspecialchars($version) . '.</p>';
51+
return;
52+
}
53+
54+
$verBlock = $releases[$version];
55+
$fullVersion = isset($verBlock['version']) ? $verBlock['version'] : $version;
56+
57+
$baseDownloads = 'https://downloads.php.net/~windows/releases/';
58+
59+
function ws_build_label(string $k, array $entry): string {
60+
$tool = 'VS';
61+
if (strpos($k, 'vs17') !== false) { $tool .= '17'; }
62+
elseif (strpos($k, 'vs16') !== false) { $tool .= '16'; }
63+
elseif (strpos($k, 'vc15') !== false) { $tool = 'VC15'; }
64+
65+
$arch = (strpos($k, 'x64') !== false) ? 'x64' : ((strpos($k, 'x86') !== false) ? 'x86' : '');
66+
$ts = (strpos($k, 'nts') !== false) ? 'Non Thread Safe' : 'Thread Safe';
67+
if (strncmp($k, 'nts-', 4) === 0) {
68+
$ts = 'Non Thread Safe';
69+
} elseif (strncmp($k, 'ts-', 3) === 0) {
70+
$ts = 'Thread Safe';
71+
}
72+
73+
$mtime = isset($entry['mtime']) ? strtotime($entry['mtime']) : 0;
74+
$mt = $mtime ? gmdate('Y-M-d H:i:s', $mtime) : '';
75+
return trim(($tool ? $tool . ' ' : '') . ($arch ? $arch . ' ' : '') . $ts . ($mt ? ' (' . $mt . ' UTC)' : ''));
76+
}
77+
78+
echo '<h3>PHP ' . htmlspecialchars($version) . ' (' . htmlspecialchars($fullVersion) . ')</h3>';
79+
80+
if (!empty($verBlock['source']['path'])) {
81+
echo '<p><a href="' . $baseDownloads . htmlspecialchars($verBlock['source']['path']) . '">Download source code</a> [' . htmlspecialchars($verBlock['source']['size'] ?? '') . ']</p>';
82+
}
83+
if (!empty($verBlock['test_pack']['path'])) {
84+
echo '<p><a href="' . $baseDownloads . htmlspecialchars($verBlock['test_pack']['path']) . '">Download tests package (phpt)</a> [' . htmlspecialchars($verBlock['test_pack']['size'] ?? '') . ']</p>';
85+
}
86+
87+
$buckets = [
88+
'nts-x64' => [],
89+
'ts-x64' => [],
90+
'nts-x86' => [],
91+
'ts-x86' => [],
92+
];
93+
94+
foreach ($verBlock as $k => $entry) {
95+
if (!is_array($entry)) { continue; }
96+
if (in_array($k, ['version', 'source', 'test_pack'], true)) { continue; }
97+
98+
$isNts = (strncmp($k, 'nts-', 4) === 0) || (strpos($k, 'nts') !== false);
99+
$arch = (strpos($k, 'x64') !== false) ? 'x64' : ((strpos($k, 'x86') !== false) ? 'x86' : '');
100+
$bucketKey = ($isNts ? 'nts' : 'ts') . '-' . ($arch !== '' ? $arch : 'other');
101+
if (!isset($buckets[$bucketKey])) { $bucketKey = 'other'; }
102+
$buckets[$bucketKey][] = [$k, $entry];
103+
}
104+
105+
foreach (['nts-x64', 'ts-x64', 'nts-x86', 'ts-x86', 'other'] as $bk) {
106+
foreach ($buckets[$bk] as [$k, $entry]) {
107+
$label = ws_build_label($k, $entry);
108+
if ($label === '') { continue; }
109+
110+
echo '<div class="win-build">';
111+
echo '<h4>' . htmlspecialchars($label) . '</h4>';
112+
113+
foreach(['zip', 'debug_pack', 'devel_pack'] as $type) {
114+
if (!empty($entry[$type]['path'])) {
115+
$p = htmlspecialchars($entry[$type]['path']);
116+
echo '<p><strong><a href="' . $baseDownloads . $p . '">' . ucfirst($type) . '</a></strong> [' . htmlspecialchars($entry[$type]['size'] ?? '') . ']<br>';
117+
echo 'sha256: ' . htmlspecialchars($entry[$type]['sha256'] ?? '') . '</p>';
118+
}
119+
}
120+
121+
echo '</div>';
122+
}
123+
}
124+
125+
?>

styles/code-syntax.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,13 @@ button.copy-to-clipboard-button:hover {
6363
border-color: var(--dark-magenta-color) !important;
6464
}
6565

66+
.win-build {
67+
background: rgba(39, 40, 44, 0.05);
68+
margin: 20px 0;
69+
padding: 20px 20px 10px 20px;
70+
border-top: 4px solid var(--dark-blue-color, #4F5B93);
71+
}
72+
73+
.win-build h4 {
74+
line-height: 1.5rem;
75+
}

0 commit comments

Comments
 (0)