Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
b64dfa0
Revamp
May 31, 2026
14eeeb5
Remove test files from sandbox
Jun 3, 2026
329363f
Clickable cards instead of buttons.
Jun 3, 2026
4675cb1
Style tweaks
Jun 3, 2026
1f33b1e
Note about todo on NewsHandler
Jun 3, 2026
2ee3811
Provide for IDs on cards for some fancy background transition stuff l…
Jun 3, 2026
63363f7
Additional prep for more fancy background loading
Jun 3, 2026
674f150
Text tweak for ecosystem
Jun 3, 2026
5135d9b
Fix reddit community link
Jun 3, 2026
1815682
Shimmer mi timbers, I collided the CSS names.
Jun 3, 2026
c91a806
Fix: Always enforce landing-card-ovh so don't need to repeat it
Jun 4, 2026
f9f2f48
Cleanup router.
Jun 4, 2026
52bdb77
Cleanup router - But still need to fix 0.0.0.0 binding via docker.
Jun 4, 2026
b11a4ff
Ultimate trycatch of ultimate destiny.
Jun 4, 2026
b5335ba
Undo the ultimate trycatch of ultimate destiny.
Jun 4, 2026
8eaa6f0
Fix default 'a' border style being inherited on l anding-card-btn
Jun 4, 2026
be6f0cc
Add a script to pull down the dynamically generated files directly fr…
Jun 4, 2026
f0868fc
Update conferences with teaser date checks and proper linking
Jun 4, 2026
f39a9e2
Replace externals with internals
Jun 4, 2026
3b90efd
All sorts of tweaks I forgot to commit, but mainly colour theming.
Jun 4, 2026
be15ab1
Docker ignore
Jun 4, 2026
fdc8faf
fix animate disabling
Jun 4, 2026
b2ed7a9
Update previous 8.x hero pages to point to 8.5
Jun 4, 2026
ae63bc1
Update $MYSITE to use HTTP_HOST
Jun 4, 2026
060d88d
Remove old index
Jun 4, 2026
34db0f3
Promote new index
Jun 4, 2026
ca40377
Undo docs.php changes for now
Jun 4, 2026
5b5b892
Use theming based on query param for testing
Jun 4, 2026
a3207ce
Moar packages!
Jun 4, 2026
4c364ed
Move the foundation sponsors into their own file.
Jun 4, 2026
399df4f
Comment out tagline for now
Jun 4, 2026
6cff7a4
Updates sync-pregen to copy into an untracked location
Jun 5, 2026
0e9ff97
Pause the sponsors on hover. Import scripts using the header.
Jun 5, 2026
31ebc9c
Drop back to 8.2
Jun 5, 2026
5055370
Major theming tweaks; break out reusable styles into their own component
Jun 5, 2026
59c8cb8
Include light and dark images
Jun 5, 2026
ead08cd
slightly moar pad, slightly moar elephpant
Jun 5, 2026
b8913da
Prep work for structured data version pages.
Jun 5, 2026
5451bb9
Restore DO NOT MODIFY file warning to files I ... modified
Jun 5, 2026
3326bba
Prebuilt release comparison file.
Jun 5, 2026
e9845f3
Add "PHP Developers" community.
Jun 5, 2026
fcc9f69
don't need flags for now
Jun 6, 2026
ed0f7e9
update initial samples with short names
Jun 6, 2026
8ee4702
Cache get_all_branches
Jun 6, 2026
cad3746
Ensure that OLDRELASES are defined into GLOBALS even if included else…
Jun 6, 2026
800ddaa
Ensure that OLDRELASES are defined into GLOBALS even if included else…
Jun 6, 2026
a3f281e
Start of structured data
Jun 6, 2026
1989ec9
Include GST theme in standard headers
Jun 6, 2026
1081646
Update RELEASES to force assign to globals
Jun 6, 2026
91e7779
Missed removing a flag
Jun 6, 2026
e5e4fa6
Partially build release comparisons
Jun 6, 2026
92d993a
Introduce accept mapper, for eventual conversion to hashed assets
Jun 6, 2026
4f55011
support label not relevant in branch-meta
Jun 6, 2026
56e753c
Save the short version in the version highlights builder.
Jun 6, 2026
1d0bae5
foundation sponsors todo
Jun 6, 2026
8160e16
Sort releases in allReleaseDataByVersionByLabel
Jun 6, 2026
e0b853a
restore style
Jun 6, 2026
04144f3
Utility helper for buffering
Jun 6, 2026
bece217
Move release highlight data
Jun 7, 2026
2aa4d48
Move existing release announcements
Jun 7, 2026
0247ed2
Update more release announcements
Jun 7, 2026
a521dba
Add compiled changelists
Jun 7, 2026
1d6a82e
Nobuild
Jun 7, 2026
b41686c
Reverse order of nav items in announcement page
Jun 7, 2026
03d63de
we don't need no templatation
Jun 7, 2026
fcaa04a
Move docker location
Jun 7, 2026
d7c4526
Docker should have been local copy
Jun 7, 2026
f9e91ab
Fix wrap on hash on release announcement page
Jun 7, 2026
305182d
Fix migration path and update index
Jun 7, 2026
af63cc0
Custom page header
Jun 7, 2026
4f719b6
Remove distribution url prefixing
Jun 7, 2026
028b8e8
Updated compiled changelists
Jun 7, 2026
ad2c0ee
Update news creation to filter previous versions
Jun 7, 2026
a19668a
Animated banner helper
Jun 7, 2026
3bf622b
Remove all method until we need it... probably soon
Jun 7, 2026
f318065
Remove parsed changelog references until we can get a proper build
Jun 7, 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
  •  
  •  
  •  
15 changes: 15 additions & 0 deletions .docker/dev/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# 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

WORKDIR /app
15 changes: 15 additions & 0 deletions .docker/prod/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# "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.2-cli

# All of the files from the source location are copied into
# the /app folder
RUN mkdir /app
WORKDIR /app
COPY . /app

RUN php -S 8080 .router
6 changes: 6 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# .dockerignore
.git
.gitmodules
.gitattributes
.idea
build-deploy.sh
7 changes: 7 additions & 0 deletions .router.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,19 @@

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

//die(print_r($_SERVER, true));

//$_SERVER['HTTP_HOST'] = '';
//$_SERVER['BASE_PAGE'] = '/';
//$_SERVER['SERVER_NAME'] = 'localhost';

if (!file_exists($_SERVER["DOCUMENT_ROOT"] . $filename)) {
require_once __DIR__ . '/error.php';

return;
}


/* This could be an image or whatever, so don't try to compress it */
ini_set("zlib.output_compression", 0);
return false;
2 changes: 1 addition & 1 deletion bin/bumpRelease
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ $OLDRELEASES[$major] = array_merge(
);

file_put_contents(__DIR__ . "/../include/releases.inc", [
"<?php\n\$OLDRELEASES = ",
'<?php' . PHP_EOL . PHP_EOL . '$GLOBALS[\'OLDRELEASES\'] = $OLDRELEASES = ',
var_export($OLDRELEASES, true),
";\n",
]);
Expand Down
148 changes: 148 additions & 0 deletions bin/compile-release-highlights.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
<?php

if (php_sapi_name() !== 'cli') {
die('This script must be run from the command line.');
}

final readonly class Segment
{
/**
* @param list<array<string, string>> $headers
*/
public function __construct(
public array $headers,
public string $body,
) {
}

public function getSingleHeader(string $key, mixed $default = null): mixed
{
return $this->headers[$key][0] ?? $default;
}

public function getHeader(string $key): array
{
return $this->headers[$key] ?? [];
}
}

/**
* @return array<string, Segment[]>
*/
function readSegmentedFile(string $path): array
{
$contents = file_get_contents($path)
?: throw new ValueError('Unable to read ' . $path);
$contents = str_replace("\r\n", "\n", $contents);
$contentSections = explode('==============================================', $contents);
$grouped = [];

foreach($contentSections as $section) {
$blocks = explode("\n\n", trim($section), 2);

/* like HTTP, blocks are a set of key-values, followed by a double newline, followed by */
$headers = [];
foreach (explode("\n", $blocks[0]) as $headerLine) {
$parts = explode(":", trim($headerLine), 2);
if (count($parts) !== 2) {
continue;
}

[$id, $value] = $parts;
$headers[$id][] = trim($value);
}

$body = $blocks[1] ?? '';
$grouped[$headers['type'][0] ?? '_'][] = new Segment(
headers: $headers,
body: $body,
);
}

return $grouped;
}

/**
* @param array<string, Segment[]> $segments
*/
function parseSegments(array $segments): array
{
$meta = $segments['meta'][0] ?? throw new ValueError('Segment "meta" cannot be found');

$examples = [];
foreach ($segments['example'] ?? [] as $example) {
$label = $example->getSingleHeader('label', '');
$target = $example->getSingleHeader('target', '');

if ($label === '' && $target !== '') {
$targetFilters = [
'<=' => '%s or Before',
'>=' => '%s or Later',
'<' => 'Before %s',
'>' => 'After %s',
];

foreach ($targetFilters as $searchKey => $englishKey) {
if (str_starts_with($target, $searchKey)) {
$label = str_replace('%s', 'PHP ' . substr($target, strlen($searchKey)), $englishKey);
break;
}
}
}

if ($label === '' && $target !== '') {
$label = $target . ' or Later';
}

if ($label === '') {
$label = 'Example';
}

$examples[] = [
'label' => $label,
'target' => $target,
'format' => $example->getSingleHeader('format', 'php'),
'body' => $example->body,
];
}

return [
'title' => $meta->getSingleHeader('title', 'Example'),
'about' => ($segments['about'][0] ?? null)?->body,
'short' => ($segments['short'][0] ?? null)?->body,
'rfs' => $meta->getHeader('rfc'),
'examples' => $examples,
];
}

function parseDirectory(string $path): array
{
$examples = [];

foreach (scandir($path) as $fileName) {
if (!str_ends_with($fileName, '.txt')) {
continue;
}

$examples[] = parseSegments(readSegmentedFile($path . '/' . $fileName));
}

return $examples;
}

$baseDir = __DIR__ . '/../data/releases';
$releaseComparisons = [];

foreach (scandir($baseDir) as $fileName) {
$dirName = $baseDir . '/' . $fileName;
if ($fileName[0] === '.') {
continue;
}

$releaseComparisons[$fileName] = parseDirectory($dirName . '/highlights');
}

file_put_contents(
__DIR__ . '/../include/releases-comparisons.inc',
'<?php return ' . var_export($releaseComparisons, true) . ';',
);
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;
}
34 changes: 24 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,34 @@ $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);
$announcementPath = $announcementsDir . '/' . $nameWithUnderscores . '.html';

is_dir($announcementsDir) or mkdir($announcementsDir, recursive: true);
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
64 changes: 64 additions & 0 deletions bin/move-release-announcements.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

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

/*
* Release announcements previously were output directly as
* PHP pages to /releases/major_minor_patch.php including the rendering
* of the header and footer.
*
* The script moves the underlying data into HTML files within the data
* directory, which can then be picked up dynamically and rendered via
* templates rather than plain files.
*/

$originalDir = realpath(__DIR__ . '/../releases');
$replacementTemplate = file_get_contents(__DIR__ . '/templates/announcement-archive.txt');

foreach (scandir($originalDir) as $file) {
if (!preg_match('/^(\d+_\d+_\d+)(?:_([a-zA-Z]+)).php$/', $file, $matches)) {
continue;
}
$lang = $matches[2] ?? '';

$fullPath = $originalDir . '/' . $file;
[$major, $minor, $patch] = explode('_', $matches[1]);


$saveDir = __DIR__ . '/../data/releases/' . $major . '.' . $minor . '/announcements';
is_dir($saveDir) || mkdir($saveDir, recursive: true);

$content = file_get_contents($fullPath)
?: throw new RuntimeException('Unable to open file: ' . $fullPath);

/* if the content has already been migrated */
if (str_contains($content, 'handle_release_announcement')) {
continue;
}

$htmlStartToken = '?>';
$htmlStartPosition = strpos($content, $htmlStartToken);
if ($htmlStartPosition === false) {
throw new RuntimeException('Unable to find PHP closing tag in ' . $fullPath);
}

$htmlStartPosition+= strlen($htmlStartToken);

$htmlEndToken = '<?php';
$htmlEndingPosition = strpos($content, $htmlEndToken, $htmlStartPosition);
if ($htmlEndingPosition === false) {
throw new RuntimeException('Unable to find PHP opening tag in ' . $fullPath);
}

$htmlContent = substr(
$content,
$htmlStartPosition,
$htmlEndingPosition - $htmlStartPosition);

$savePath = $saveDir . '/' . $major . '_' . $minor . '_' . $patch . ($lang ? "_$lang" : '') .'.html';
file_put_contents($savePath, trim($htmlContent));

/* the original file gets modified to use a version-specific template */
$code = str_replace('{{version}}', $major . '.' . $minor . '.' . $patch, $replacementTemplate);
file_put_contents($fullPath, $code);
}
9 changes: 9 additions & 0 deletions bin/news2html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<?php
PHP_SAPI == 'cli' or die("Please run this script using the cli sapi");

require_once __DIR__ . '/util.php';

// get args
$cmd = array_shift($_SERVER['argv']);

Expand Down Expand Up @@ -109,3 +111,10 @@ if ($changelog) {
$log = str_replace($tag, "$tag\n\n$contents", $log);
file_put_contents($changelog, $log);
}

[$major, $minor] = explode($version, '.');
$branch = $major.'.'.$minor;
NewsParsingHelper::writeChangeMetaToBranch(
branch: $branch,
data: NewsParsingHelper::parseNewsFileToString($branch, $news_file),
);
Loading