Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
163 commits
Select commit Hold shift + click to select a range
01c12db
Revamp
May 31, 2026
37045e9
Remove test files from sandbox
Jun 3, 2026
ed9017a
Clickable cards instead of buttons.
Jun 3, 2026
6647420
Style tweaks
Jun 3, 2026
1fe6a09
Note about todo on NewsHandler
Jun 3, 2026
cda17b2
Provide for IDs on cards for some fancy background transition stuff l…
Jun 3, 2026
370d7bb
Additional prep for more fancy background loading
Jun 3, 2026
d0d7ba9
Text tweak for ecosystem
Jun 3, 2026
ec22789
Fix reddit community link
Jun 3, 2026
da1fe10
Shimmer mi timbers, I collided the CSS names.
Jun 3, 2026
b56a0e2
Fix: Always enforce landing-card-ovh so don't need to repeat it
Jun 4, 2026
d8b8729
Cleanup router.
Jun 4, 2026
4c3917d
Cleanup router - But still need to fix 0.0.0.0 binding via docker.
Jun 4, 2026
6026401
Ultimate trycatch of ultimate destiny.
Jun 4, 2026
7995f56
Undo the ultimate trycatch of ultimate destiny.
Jun 4, 2026
2902415
Fix default 'a' border style being inherited on l anding-card-btn
Jun 4, 2026
12c29c1
Add a script to pull down the dynamically generated files directly fr…
Jun 4, 2026
8cf77e9
Update conferences with teaser date checks and proper linking
Jun 4, 2026
4c10cb2
Replace externals with internals
Jun 4, 2026
64b03f1
All sorts of tweaks I forgot to commit, but mainly colour theming.
Jun 4, 2026
1c82bbf
Docker ignore
Jun 4, 2026
4fabc72
fix animate disabling
Jun 4, 2026
0504184
Update previous 8.x hero pages to point to 8.5
Jun 4, 2026
6d67d7f
Update $MYSITE to use HTTP_HOST
Jun 4, 2026
d8db9f4
Remove old index
Jun 4, 2026
65f6889
Promote new index
Jun 4, 2026
c9d2cd9
Undo docs.php changes for now
Jun 4, 2026
106edc8
Use theming based on query param for testing
Jun 4, 2026
aa8d06d
Moar packages!
Jun 4, 2026
d148f05
Move the foundation sponsors into their own file.
Jun 4, 2026
8d38363
Comment out tagline for now
Jun 4, 2026
92f9ce0
Updates sync-pregen to copy into an untracked location
Jun 5, 2026
1a1c263
Pause the sponsors on hover. Import scripts using the header.
Jun 5, 2026
d52a8ce
Drop back to 8.2
Jun 5, 2026
e391b10
Major theming tweaks; break out reusable styles into their own component
Jun 5, 2026
14fc938
Include light and dark images
Jun 5, 2026
2542393
slightly moar pad, slightly moar elephpant
Jun 5, 2026
f0d7e52
Prep work for structured data version pages.
Jun 5, 2026
7517a70
Restore DO NOT MODIFY file warning to files I ... modified
Jun 5, 2026
9ce193c
Prebuilt release comparison file.
Jun 5, 2026
d935ac3
Add "PHP Developers" community.
Jun 5, 2026
e0f2fc3
don't need flags for now
Jun 6, 2026
3b241ab
update initial samples with short names
Jun 6, 2026
670132e
Cache get_all_branches
Jun 6, 2026
de92284
Ensure that OLDRELASES are defined into GLOBALS even if included else…
Jun 6, 2026
4696f1f
Start of structured data
Jun 6, 2026
5520eff
Include GST theme in standard headers
Jun 6, 2026
acd002a
Update RELEASES to force assign to globals
Jun 6, 2026
d518c75
Missed removing a flag
Jun 6, 2026
a7f1329
Partially build release comparisons
Jun 6, 2026
e933f5b
Introduce accept mapper, for eventual conversion to hashed assets
Jun 6, 2026
10d5893
support label not relevant in branch-meta
Jun 6, 2026
3103833
Save the short version in the version highlights builder.
Jun 6, 2026
dac66a8
foundation sponsors todo
Jun 6, 2026
6b4ec93
Sort releases in allReleaseDataByVersionByLabel
Jun 6, 2026
9491158
restore style
Jun 6, 2026
0db51d4
Utility helper for buffering
Jun 6, 2026
9bd32a7
Move release highlight data
Jun 7, 2026
3afa8c5
Move existing release announcements
Jun 7, 2026
bfb3820
Update more release announcements
Jun 7, 2026
a1d728b
Add compiled changelists
Jun 7, 2026
bf2eee8
Nobuild
Jun 7, 2026
0d4be50
Reverse order of nav items in announcement page
Jun 7, 2026
3e57e53
we don't need no templatation
Jun 7, 2026
20647d2
Move docker location
Jun 7, 2026
3c4b436
Docker should have been local copy
Jun 7, 2026
bdac289
Fix wrap on hash on release announcement page
Jun 7, 2026
5005037
Fix migration path and update index
Jun 7, 2026
8ba1498
Custom page header
Jun 7, 2026
90cf320
Remove distribution url prefixing
Jun 7, 2026
9078409
Updated compiled changelists
Jun 7, 2026
3063afb
Update news creation to filter previous versions
Jun 7, 2026
fe2c056
Animated banner helper
Jun 7, 2026
03ebe79
Remove all method until we need it... probably soon
Jun 7, 2026
42c7795
Remove parsed changelog references until we can get a proper build
Jun 7, 2026
09e4f24
Migration URL can go straight to the manual page.
Jun 7, 2026
43d0184
The var cache is a utility to help store variables that are compiled.
Jun 7, 2026
48abde1
Update the release highlights to use VarCache
Jun 7, 2026
5abf71d
Don't need these old changelists anymore now we've moved to VarCache …
Jun 7, 2026
d9cb09d
Announcement parser now uses varcache
Jun 7, 2026
9c80429
Update the metadata to releases namespace
Jun 7, 2026
cf0751d
Cache annotations
Jun 7, 2026
0d904db
Fix namespace update which did not update filepaths
Jun 7, 2026
ab64126
Include state detection in VersionData
Jun 7, 2026
63337e0
Missed a namespace change
Jun 7, 2026
897a49d
Move version date manipulations into VersionData handler.
Jun 8, 2026
7dc8be3
Misc file.
Jun 8, 2026
14268cb
How much I hate global variables...
Jun 8, 2026
d49fea7
Fix more issues with variable declaration at top level of files...
Jun 8, 2026
e1f6794
Attempt to eliminate all uses of the quasi-superglobal RELEASES and O…
Jun 8, 2026
d515b11
Allow passing DateTimeImmutables into format_interval.
Jun 8, 2026
e743ac2
Test support states in test-dates because it's there
Jun 8, 2026
84d0cdc
Update supported-versions with the new code.
Jun 8, 2026
e9ade6c
More trailing $RELEASES and $OLDRELEASES in /releases/index.php
Jun 8, 2026
1b2ba39
Fix auto refactor glitch on assets/images
Jun 8, 2026
c034025
Upgrade supported-versions SVG generator to use VersionData and wrap …
Jun 8, 2026
4fe2631
Add sorting and keying helpers to VersionData
Jun 8, 2026
d0f5757
Update releases/branches.php API to use VersionData
Jun 8, 2026
cfa18ac
Update eol.php to use VersionData
Jun 8, 2026
936df5e
Missed namespace update on retro-create-news.php
Jun 8, 2026
12cfa95
Wrap the release manager's GPG keys into an auto-loadable helper.
Jun 8, 2026
6e44aa4
Update thanks.php to rely upon return value from require, not a globa…
Jun 8, 2026
f6605f4
Docs and fixes for the release metadata
Jun 8, 2026
f3c8d86
Latest version bump
Jun 8, 2026
591ceb9
Better missing logo handling
Jun 8, 2026
fc499a6
Old NEWS file used to use - not .
Jun 8, 2026
a857d36
Move NewsParsingHelper
Jun 8, 2026
0c42e0e
Logo returns empty string
Jun 8, 2026
5c76cc0
Tweaks to VersionData loading
Jun 8, 2026
97dccf1
Builder helpers part 2
Jun 8, 2026
f88ff92
Break out the build step for the version highlights.
Jun 8, 2026
e33788d
Change the announcement location
Jun 8, 2026
4510d6f
Move release files
Jun 8, 2026
c104caf
full version
Jun 8, 2026
6e7fb5a
Create data loader and build step for announcements
Jun 8, 2026
7bd46bc
more build steppage
Jun 8, 2026
2cd6a7b
Remove the release announcements from the git repo.
Jun 8, 2026
b757116
Router hardening.
Jun 8, 2026
422491e
Fix source cache initializer
Jun 9, 2026
0565a7c
Add phpstan to composer
Jun 9, 2026
549a1d2
Additional tooling for dev container
Jun 9, 2026
58d78ee
Hello phpstan my old friend
Jun 9, 2026
f1d23b9
phpstan pass on ChangeLogDataLoader
Jun 9, 2026
aff2583
Filesystem helper, avoids var|false in static analysis
Jun 9, 2026
fe6cf5d
phpstan pass on ReleaseHighlightsDataLoader
Jun 9, 2026
e24e7c4
phpstan pass on SupportTimelineSvgGenerator, separated out config for…
Jun 9, 2026
d73b123
phpstan pass on PointReleaseData
Jun 9, 2026
b0c1eaa
phpstan pass on VersionData
Jun 9, 2026
286da97
phpstan pass on VersionData
Jun 9, 2026
dedc188
phpstan pass on VersionData
Jun 9, 2026
461f907
double docblock fix
Jun 9, 2026
9b8c7ce
Don't recreate HighlightArray
Jun 9, 2026
26a06ff
phpstan pass on ProjectGlobals
Jun 9, 2026
9d86fe0
bufferOutput throws if it cannot close buffer.
Jun 9, 2026
2bf631c
type annotation fix on SampleMultipartSegment
Jun 9, 2026
f4a54b6
Split out the version comparison functions
Jun 9, 2026
00ed66d
Split out the version comparison functions
Jun 9, 2026
008c856
More phpstan
Jun 9, 2026
f2b5b8c
More phpstan fixes
Jun 9, 2026
458a218
fix dateOverrides
Jun 9, 2026
a89c464
fix docblocks on VersionData branch overrides
Jun 9, 2026
c709616
simplify rekey
Jun 9, 2026
8c4bfe2
Make majorFeatureDescriptions be getter
Jun 9, 2026
1bd28c0
Lowercase create
Jun 9, 2026
ad56793
phpstan fixes for UserNotes
Jun 9, 2026
32d0013
More tweaks to VersionData _majorFeatureDescriptions
Jun 9, 2026
1d80c61
Types + default values on Sorter
Jun 9, 2026
ed4a9c0
more docblocks
Jun 9, 2026
dd02914
Clone with fixes
Jun 9, 2026
93c1e64
Push build
Jun 9, 2026
bbf14c8
Remove caching from the landing page - CDN handles it.
Jun 9, 2026
25690f7
SAPI protection on build.php
Jun 9, 2026
e5fe92b
Here be changes.txt
Jun 9, 2026
0dfed7f
Some changes.txt that got overwritten
Jun 9, 2026
3f186e5
Start of going all-in on build-time version+release data
Jun 9, 2026
6e4431a
8.0.4 never existed properly due to a security situation, need to bac…
Jun 9, 2026
02bd959
Finish migrating the change log loaders
Jun 9, 2026
b88e78d
Remove reference to release_get_latest - Did impact mirror-info.php, …
Jun 9, 2026
bfee04a
Removed version_compare from branches.inc
Jun 9, 2026
d67729f
Strip out more dead functions from branches.inc
Jun 9, 2026
57cfc9d
Remove get_eol_branches and move better logic into releases/index.php…
Jun 9, 2026
cf47053
Missed removal of EOL timestamp
Jun 9, 2026
7b88ea9
Upgrading to releases page
Jun 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
46 changes: 46 additions & 0 deletions .docker/dev/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Development Docker
#
# Provides the main runtime engine as well as tooling for running
# during development
#
# NOTES:
# - Does not copy and files in as it is expected to be handled via a mount

FROM php:8.4-cli

# Codebase doesn't have production flag so we negate it instead with
# the DEVELOPMENT flag
ENV DEVELOPMENT=1

#
# install additional development tooling
#
RUN apt update \
&& apt-get install -y --no-install-recommends git unzip \
&& rm -rf /var/lib/apt/lists/*

#
# Composer is required for dev dependencies
#
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
&& php -r "if (hash_file('sha384', 'composer-setup.php') === 'c8b085408188070d5f52bcfe4ecfbee5f727afa458b2573b8eaaf77b3419b0bf2768dc67c86944da1544f06fa544fd47') { echo 'Installer verified'.PHP_EOL; } else { echo 'Installer corrupt'.PHP_EOL; unlink('composer-setup.php'); exit(1); }" \
&& php composer-setup.php \
&& php -r "unlink('composer-setup.php');" \
&& mv composer.phar /usr/local/bin/composer

#
# node.js - used for socket.dev and other front-end tooling
#
RUN apt-get update && apt-get install -y curl gnupg ca-certificates \
&& mkdir -p /etc/apt/keyrings \
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list \
&& apt-get update && apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*

#
# Global dependencies and tools brought in via npm
#
RUN npm install -g socket

WORKDIR /app
13 changes: 13 additions & 0 deletions .docker/prod/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# "Production" Docker
#
# Provides the main runtime for PHP when deploying to a "Production"
# or "Testing" environment that needs a full container using
# the inbuilt server (not recommended).

FROM php:8.4-cli

# All of the files from the source location are copied into
# the /app folder
RUN mkdir /app
WORKDIR /app
COPY . /app
7 changes: 7 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# .dockerignore
.git
.gitmodules
.gitattributes
.idea
build-deploy.sh
/var/composer
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ node_modules/
/playwright-report/
/blob-report/
/playwright/.cache/
/releases/[0-9]*_[0-9]*_[0-9]*.php
/releases/[0-9]*_[0-9]*_[0-9]*_fr.php
/releases/[0-9]*_[0-9]*_[0-9]*_win32.php
28 changes: 27 additions & 1 deletion .router.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,38 @@

$filename = $_SERVER["PATH_INFO"] ?? $_SERVER["SCRIPT_NAME"];

if (!file_exists($_SERVER["DOCUMENT_ROOT"] . $filename)) {
$wantedPath = realpath($_SERVER["DOCUMENT_ROOT"] . $filename);
if ($wantedPath === false || !str_starts_with($wantedPath, __DIR__ . '/')) {
require_once __DIR__ . '/error.php';

return;
}

/**
* Unfortunately, we do not yet have a dedicated public folder, meaning the entire directory
* structure is exposed.
*
* These rules try and lock it down some.
*/
foreach ([
'.git/*',
'.docker/*',
'.devcontainer/*',
'.github/*',
'backend/*',
'bin/*',
'data/*',
'src/*',
'tests/*',
'var/*',
'*.inc', // do not allow any .inc files
] as $testRule) {
if (fnmatch(__DIR__ . '/' . $testRule, $wantedPath, FNM_CASEFOLD)) {
header('HTTP/1.0 403 Access Denied');
die('Access Denied');
}
}

/* This could be an image or whatever, so don't try to compress it */
ini_set("zlib.output_compression", 0);
return false;
40 changes: 40 additions & 0 deletions bin/build.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

use phpweb\Build\BuildGlobals;
use phpweb\Build\BuildStepFailureException;
use phpweb\Releases\Build\ReleasePagesBuilder;
use phpweb\Releases\ChangeLogs\ChangeLogDataLoader;
use phpweb\Releases\Data\ReleaseAnnouncementsDataLoader;
use phpweb\Releases\Data\ReleaseHighlightsDataLoader;
use phpweb\Releases\ReleaseRawDataLoader;

(PHP_SAPI === 'cli') or die("Please run this script using the cli sapi");

require_once __DIR__ . '/../src/autoload.php';

$buildSteps = [
ReleaseRawDataLoader::class,
ChangeLogDataLoader::class,
ReleaseHighlightsDataLoader::class,
ReleaseAnnouncementsDataLoader::class,
ReleasePagesBuilder::class,
];

/* protect us against doing silly things */
BuildGlobals::$building = true;

foreach ($buildSteps as $classId) {
printf("Building step %s\n", $classId);

try {
$classId::build();
} catch (BuildStepFailureException $e) {
fwrite(STDERR, 'Error building ' . $classId . ': ' . $e->getMessage());
exit(1);
} catch (Throwable $e) {
fwrite(STDERR, 'Unhandled exception building ' . $classId . ': ' . $e->getMessage() . "\n");
fwrite(STDERR, $e->getTraceAsString() . "\n");
die($e);
exit(1);
}
}
8 changes: 3 additions & 5 deletions bin/bumpRelease
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,18 @@
(PHP_SAPI === 'cli') or die("Please run this script using the cli sapi");

require_once __DIR__ . "/../include/branches.inc";
require_once __DIR__ . "/../include/version.inc";
require_once __DIR__ . "/../include/releases.inc";

if ($_SERVER['argc'] < 1) {
fwrite(STDERR, "Usage: {$_SERVER['argv'][0]} major_version [ minor_version ]\n");
exit(1);
}

$major = (int) $_SERVER['argv'][1];
isset($RELEASES[$major]) or die("Unknown major version $major");
isset(get_releases()[$major]) or die("Unknown major version $major");
$minor = isset($_SERVER['argv'][2]) ? (int) $_SERVER['argv'][2] : null;

$version = get_current_release_for_branch($major, $minor);
$info = $RELEASES[$major][$version] ?? null;
$info = get_releases()[$major][$version] ?? null;

if ($info === null) {
fwrite(STDERR, "Unable to find a current PHP release for {$major}.{$minor}\n");
Expand All @@ -34,7 +32,7 @@ $OLDRELEASES[$major] = array_merge(
);

file_put_contents(__DIR__ . "/../include/releases.inc", [
"<?php\n\$OLDRELEASES = ",
'<?php' . PHP_EOL . PHP_EOL . 'return ',
var_export($OLDRELEASES, true),
";\n",
]);
Expand Down
19 changes: 19 additions & 0 deletions bin/createNewsEntry
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ function parseOptions(): Entry {
echo " --conf-time 'value' When the event will be occurign (cfp and conference categories only)\n";
echo " --content 'value' Text content for the entry, may include XHTML\n";
echo " --content-file 'value' Name of file to load content from, may not be specified with --content\n";
echo " --summary 'value' Short, plain-text summary of the content. Should be a single line.\n";
echo " --summary-file 'value' Name of the file to load summary content from, should be a plain-text summary of the content. Should be a single line.\n";
echo " --image-path 'value' Basename of image file in " . Entry::IMAGE_PATH_REL . "\n";
echo " --image-title 'value' Title for the image provided\n";
echo " --image-link 'value' URI to direct to when clicking the image\n";
Expand Down Expand Up @@ -238,5 +240,22 @@ function parseOptions(): Entry {
exit(1);
}

$summary = $opts['summary'] ?? '';
$summaryFile = $opts['summary-file'] ?? '';
if ($summary && $summaryFile) {
fwrite(STDERR, "--summary and --summary-file may not be specified together\n");
exit(1);
} elseif ($summaryFile) {
$summary = file_get_contents($summaryFile);
if ($summary === false) {
fwrite(STDERR, "Summary cannot be opened, or must not be empty\n");
exit(1);
}
}

if ($summary) {
$entry->setSummary($summary);
}

return $entry;
}
33 changes: 23 additions & 10 deletions bin/createReleaseEntry
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ PHP_SAPI == 'cli' or die("Please run this script using the cli sapi");
require_once __DIR__ . '/../src/autoload.php';

use phpweb\News\Entry;
use phpweb\ProjectGlobals;

if (!file_exists(Entry::ARCHIVE_FILE_ABS)) {
fwrite(STDERR, "Can't find " . Entry::ARCHIVE_FILE_REL . ", are you sure you are in phpweb/?\n");
Expand Down Expand Up @@ -50,21 +51,33 @@ $entry = (new Entry)
$entry->save()->updateArchiveXML();
$addedFiles = [Entry::ARCHIVE_ENTRIES_REL . $entry->getId() . '.xml'];

$nameWithUnderscores = strtr($version, '.', '_');

/*
* Release announcements are stored as HTML within the data/releases/major.minor/announcements
* folder as plain HTML files, and are then included as part of other page templates
*/
$announcementsDir = ProjectGlobals::getDataPathForRelease($branch, create: true);
$announcementPath = $announcementsDir . '/' . $nameWithUnderscores . '.html';

file_put_contents($announcementPath, $template);
$addedFiles[] = $announcementPath;

// Mint the releases/x_y_z.php archive.
const RELEASES_REL = 'releases/';
const RELEASES_ABS = __DIR__ . '/../' . RELEASES_REL;
if (isset($opts['r'])) {
$release = strtr($version, '.', '_') . '.php';
file_put_contents(RELEASES_ABS . $release, "<?php
\$_SERVER['BASE_PAGE'] = 'releases/$release';
include_once __DIR__ . '/../include/prepend.inc';
site_header('PHP $version Release Announcement');
?>
<h1>PHP $version Release Announcement</h1>
/*
* The announcement content is no longer embedded straight into a page, instead we
* invoke a page template helper, passing in the release version, and it figures
* the rest out itself
*/
$release = $nameWithUnderscores . '.php';
file_put_contents(
RELEASES_ABS . $release,
str_replace('{{version}}', $version, file_get_contents(__DIR__ . '/templates/announcement-archive.txt'))
);

$template
<?php site_footer();
");
$addedFiles[] = RELEASES_REL . $release;
}

Expand Down
103 changes: 103 additions & 0 deletions bin/migrations/migrate-news.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php

/**
* Warning! Here be horrible, horrible hacks.
*
* Creates news files retroactively by pulling from GIT repositories
*
* Because this repository itself, nor any given php-src branch, has a complete record
* of the individual NEWS files in raw data, to be able to create them as serialized data,
* we have to fetch them from the github repository.
*
* We do this by looking for the most up-to-date release of each branch, which
* should theoretically contain the full set of release notes.
*
* THIS SCRIPT ONLY COPIES THE NOTES INTO THE RELEVANT DATA FOLDER, IT STILL
* REQUIRES RUNNING THE BUILD SCRIPT TO MAKE THEM VISIBLE
*/

use phpweb\ProjectGlobals;
use phpweb\Releases\ChangeLogs\ChangeLogDataLoader;
use phpweb\Releases\ReleaseRawDataLoader;
use phpweb\Util\FS;
use phpweb\Utils;

PHP_SAPI == 'cli' or die("Please run this script using the cli sapi");

require_once __DIR__ . '/../../src/autoload.php';

$branches = [];
foreach (ReleaseRawDataLoader::readReleaseDataDirectoriesFromDisk() as $versionId => $releases) {
/*
* Look for the most recent version as it's the one most likely to have the fullest
* set of data within it
*/

$highestVersion = null;
foreach (array_keys($releases) as $releaseId) {
[$major, $minor] = explode('.', $releaseId);

$br = $major . '.' . $minor;
$highestVersion = (!$highestVersion || Utils::versionCompareOp($releaseId, $highestVersion, 'gt'))
? $releaseId
: $highestVersion;
}

if (!$highestVersion) {
printf("Warning! There is no highest release of " . $versionId . " available; skipping\n");
continue;
}

$cachePath = sys_get_temp_dir() . '/php-news-' . $highestVersion . '.txt';
if (!file_exists($cachePath)) {
/* the file could be in one of a number of locations depending on how it was committed */
$options = [
/* normal branch */
'https://raw.githubusercontent.com/php/php-src/refs/heads/PHP-' . $highestVersion . '/NEWS',

/* tag */
'https://raw.githubusercontent.com/php/php-src/refs/tags/php-' . $highestVersion . '/NEWS',
];

foreach ($options as $fetchUrl) {
$content = @file_get_contents($fetchUrl);
if (!$content) {
fwrite(STDERR, "Could not read raw data for $fetchUrl\n");
continue;
}

fwrite(STDOUT, "Successfully imported read data from $fetchUrl\n");
FS::writeContents($cachePath, $content);
}

if (!$content) {
fwrite(STDERR, "Could not find a suitable data source for $highestVersion\n");
continue;
}
} else {
$content = FS::readContents($cachePath);
}

/*
* We should now, theoretically, have a complete news file that has the highest release and
* everything before it.
*
* Some of them have a ton of data before, some get reset at the start of each major.minor version
*/
foreach (ChangeLogDataLoader::parseNewsFileToReleaseSections($content) as $releaseId => $data) {
/* only write the sections that belong to us */
if (!str_starts_with($releaseId, $versionId . '.')) {
continue;
}

/* special case for 5.1.0 which doesn't have the release in the original NEWS */
if ($releaseId === '5.1') {
$releaseId = '5.1.0';
}

$path = ProjectGlobals::getDataPathForRelease($releaseId, create: true) . '/changes.txt';
if (FS::writeContentsIfChanged($path, $data)) {
printf("Writing NEWS block to %s %s\n", $path, md5($data));
}
}
}
Loading