diff --git a/downloads.php b/downloads.php
index 20c416ef6e..5468da840f 100644
--- a/downloads.php
+++ b/downloads.php
@@ -18,11 +18,12 @@
-
- - Running test suites in RC
+
- Running test suites in RC
and release distributions of PHP
- Help finding and diagnosing failed tests, see
the phpt documentation
diff --git a/include/release-qa.php b/include/release-qa.php
new file mode 100644
index 0000000000..4fe4c18efa
--- /dev/null
+++ b/include/release-qa.php
@@ -0,0 +1,170 @@
+ [
+ 'active' => true,
+ 'release' => [
+ 'type' => 'RC',
+ 'number' => 0,
+ 'sha256_gz' => '',
+ 'sha256_bz2' => '',
+ 'sha256_xz' => '',
+ 'date' => '07 Nov 2023',
+ 'baseurl' => 'https://downloads.php.net/',
+ ],
+ ],
+
+ '8.2.27' => [
+ 'active' => true,
+ 'release' => [
+ 'type' => 'RC',
+ 'number' => 0,
+ 'sha256_bz2' => '',
+ 'sha256_gz' => '',
+ 'sha256_xz' => '',
+ 'date' => '05 Dec 2024',
+ 'baseurl' => 'https://downloads.php.net/',
+ ],
+ ],
+
+ '8.3.20' => [
+ 'active' => true,
+ 'release' => [
+ 'type' => 'RC',
+ 'number' => 0,
+ 'sha256_bz2' => '',
+ 'sha256_gz' => '',
+ 'sha256_xz' => '',
+ 'date' => '27 Mar 2025',
+ 'baseurl' => 'https://downloads.php.net/',
+ ],
+ ],
+
+ '8.4.7' => [
+ 'active' => true,
+ 'release' => [
+ 'type' => 'RC',
+ 'number' => 1,
+ 'sha256_bz2' => 'acddb1da1b128f984df01347c907a64939f316d7d9bd138b49106f4179b7776f',
+ 'sha256_gz' => 'b12d97767aeda4624ea1904c1d93303efe4ffe1ba91970a3c5774ad556918e93',
+ 'sha256_xz' => '6cb37632eb65ee311cb4427ad070b6ab27fdaf13e8f0103701b2b78907326c93',
+ 'date' => '24 Apr 2025',
+ 'baseurl' => 'https://downloads.php.net/~saki/',
+ ],
+ ],
+];
+
+/*** End Configuration *******************************************************************/
+
+// This is a list of the possible checksum values that can be supplied with a QA release. Any
+// new algorithm is read from the $QA_RELEASES array under the 'release' index for each version
+// in the form of "$algorithm_$filetype".
+//
+// For example, if SHA512 were to be supported, the following indices would have to be added:
+//
+// 'sha512_bz2' => 'xxx',
+// 'sha512_gz' => 'xxx',
+// 'sha512_xz' => 'xxx',
+$QA_CHECKSUM_TYPES = ['sha256'];
+
+// $QA_RELEASES eventually contains just about everything, also for external use
+// release : These are encouraged for use (e.g., linked at qa.php.net)
+// reported : These are allowed to report @ the php.qa.reports mailing list
+
+(function(&$QA_RELEASES) use ($QA_CHECKSUM_TYPES) {
+ foreach ($QA_RELEASES as $pversion => $info) {
+
+ if (isset($info['active']) && $info['active']) {
+
+ // Allow -dev versions of all active types
+ // Example: 5.3.6-dev
+ $QA_RELEASES['reported'][] = "{$pversion}-dev";
+ $QA_RELEASES[$pversion]['dev_version'] = "{$pversion}-dev";
+
+ // Allow -dev version of upcoming qa releases (rc/alpha/beta)
+ // @todo confirm this php version format for all dev versions
+ if ((int)$info['release']['number'] > 0) {
+ $QA_RELEASES['reported'][] = "{$pversion}{$info['release']['type']}{$info['release']['number']}";
+ if (!empty($info['release']['baseurl'])) {
+
+ // php.net filename format for qa releases
+ // example: php-5.3.0RC2
+ $fn_base = 'php-' . $pversion . $info['release']['type'] . $info['release']['number'];
+
+ $QA_RELEASES[$pversion]['release']['version'] = $pversion . $info['release']['type'] . $info['release']['number'];
+ foreach ([ 'bz2', 'gz', 'xz' ] as $file_type) {
+ foreach ($QA_CHECKSUM_TYPES as $algo) {
+ if (isset($info['release'][$algo . '_' . $file_type])) {
+ $QA_RELEASES[$pversion]['release']['files'][$file_type][$algo] = $info['release'][$algo . '_' . $file_type];
+ }
+ }
+ if (!empty($QA_RELEASES[$pversion]['release']['files'][$file_type])) {
+ $QA_RELEASES[$pversion]['release']['files'][$file_type]['path']= $info['release']['baseurl'] . $fn_base . '.tar.' . $file_type;
+ }
+ }
+
+ if (empty($QA_RELEASES[$pversion]['release']['files'])) {
+ $QA_RELEASES[$pversion]['release']['enabled'] = false;
+ }
+ }
+ } else {
+ $QA_RELEASES[$pversion]['release']['enabled'] = false;
+ }
+
+ }
+ }
+
+ // Sorted information for later use
+ // @todo need these?
+ // $QA_RELEASES['releases'] : All current versions with active qa releases
+ foreach ($QA_RELEASES as $pversion => $info) {
+ if (isset($info['active']) && $info['active'] && !empty($info['release']['number'])) {
+ $QA_RELEASES['releases'][$pversion] = $info['release'];
+ }
+ }
+
+})($QA_RELEASES);
diff --git a/release-candidates.php b/release-candidates.php
new file mode 100644
index 0000000000..d3a6c46432
--- /dev/null
+++ b/release-candidates.php
@@ -0,0 +1,75 @@
+
+ Test Releases
+
+ The downloads on this page are not meant to be run in production. They are
+ for testing only.
+
+
+ If you find a problem when running your library or application with these
+ builds, please file a report on
GitHub Issues.
+
+
+';
+
+site_header("Release Candidates", [
+ 'current' => 'downloads',
+]);
+
+?>
+Release Candidate Builds
+
+This page contains links to the Release Candidate builds that the release
+managers create before each actual release. These builds are meant for the
+community to test whether no inadvertent changes have been made, and
+whether no regressions have been introduced.
+
+
+Available QA Releases:
+
+ 1 ? 's' : ''; ?>
+
+ $info) : ?>
+
+ PHP
+
+
+
+
+ $file_info) : ?>
+ -
+
+
+
+
+
+
+
+ No checksum value available)
+
+
+
+
+
+
+
+
There are no QA releases available at the moment to test.
+
+
+
+
+ Windows users:
+ See here for the Windows QA builds.
+
+
+ $SIDEBAR_DATA]);
+