[PHP-WEBMASTER] [web-php] redesign-downloads-page-prototype: Merge branch 'master' into redesign-downloads-page-prototype

Author: Sergey Panteleev (saundefined)
Committer: GitHub (web-flow)
Pusher: saundefined
Date: 2025-07-28T21:15:15+03:00

Commit: Merge branch 'master' into redesign-downloads-page-prototype · php/web-php@1d55dfc · GitHub
Raw diff: Longhorn PHP 2025 - Call For Papers

Merge branch 'master' into redesign-downloads-page-prototype

Changed paths:
  A archive/entries/2025-06-09-1.xml
  A archive/entries/2025-06-11-1.xml
  A archive/entries/2025-07-03-1.xml
  A archive/entries/2025-07-03-2.xml
  A archive/entries/2025-07-03-3.xml
  A archive/entries/2025-07-03-4.xml
  A archive/entries/2025-07-03-5.xml
  A archive/entries/2025-07-17-1.xml
  A license/ZendGrant/PHPAssociation.pdf
  A license/ZendGrant/index.php
  A releases/8_1_33.php
  A releases/8_2_29.php
  A releases/8_3_23.php
  A releases/8_4_10.php
  A src/News/NewsHandler.php
  A styles/cse-search.css
  A tests/Unit/News/NewsHandlerTest.php
  M .github/workflows/integrate.yaml
  M .github/workflows/pr-preview.yml
  M .github/workflows/update-screenshots.yaml
  M ChangeLog-8.php
  M archive/2013.php
  M archive/2014.php
  M archive/2015.php
  M archive/2016.php
  M archive/2017.php
  M archive/2018.php
  M archive/2019.php
  M archive/2020.php
  M archive/2021.php
  M archive/2022.php
  M archive/2023.php
  M archive/2024.php
  M archive/2025.php
  M archive/archive.xml
  M composer.json
  M composer.lock
  M conferences/index.php
  M copyright.php
  M distributions
  M elephpant.php
  M git.php
  M include/branches.inc
  M include/gpg-keys.inc
  M include/header.inc
  M include/layout.inc
  M include/release-qa.php
  M include/releases.inc
  M include/version.inc
  M index.php
  M js/common.js
  M license/ZendGrant/index.html
  M mailing-lists.php
  M search.php
  M styles/theme-base.css

Diff:

diff --git a/.github/workflows/integrate.yaml b/.github/workflows/integrate.yaml
index 0fb48b5e46..933a196f87 100644
--- a/.github/workflows/integrate.yaml
+++ b/.github/workflows/integrate.yaml
@@ -27,7 +27,7 @@ jobs:
         uses: "shivammathur/setup-php@v2"
         with:
           coverage: "xdebug"
- extensions: "none, curl, dom, json, mbstring, tokenizer, xml, xmlwriter"
+ extensions: "none, curl, dom, json, mbstring, tokenizer, xml, xmlwriter, iconv"
           php-version: "${{ matrix.php-version }}"

       - name: "Set up problem matchers for PHP"
@@ -72,7 +72,7 @@ jobs:
         uses: "shivammathur/setup-php@v2"
         with:
           coverage: "none"
- extensions: "none, curl, dom, json, mbstring, tokenizer, xml, xmlwriter"
+ extensions: "none, curl, dom, json, mbstring, tokenizer, xml, xmlwriter, iconv"
           php-version: "${{ matrix.php-version }}"

       - name: "Set up problem matchers for PHP"
@@ -128,7 +128,7 @@ jobs:
         uses: "shivammathur/setup-php@v2"
         with:
           coverage: "none"
- extensions: "none, curl, dom, json, mbstring, tokenizer, xml, xmlwriter"
+ extensions: "none, curl, dom, json, mbstring, tokenizer, xml, xmlwriter, iconv"
           php-version: "${{ matrix.php-version }}"

       - name: "Set up problem matchers for PHP"
diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml
index 0cdaa7b13c..0d5e88c6dc 100644
--- a/.github/workflows/pr-preview.yml
+++ b/.github/workflows/pr-preview.yml
@@ -60,7 +60,7 @@ jobs:
       - uses: shivammathur/setup-php@v2
         with:
           coverage: "none"
- extensions: "none, curl, dom, json, mbstring, tokenizer, xml, xmlwriter"
+ extensions: "none, curl, dom, json, mbstring, tokenizer, xml, xmlwriter, iconv"
           php-version: "${{ matrix.php-version }}"

       - name: Use Node.js ${{ matrix.node-version }}
diff --git a/.github/workflows/update-screenshots.yaml b/.github/workflows/update-screenshots.yaml
index 5f869615c1..ab182041b5 100644
--- a/.github/workflows/update-screenshots.yaml
+++ b/.github/workflows/update-screenshots.yaml
@@ -29,7 +29,7 @@ jobs:
         uses: "shivammathur/setup-php@v2"
         with:
           coverage: "none"
- extensions: "none, curl, dom, json, mbstring, tokenizer, xml, xmlwriter"
+ extensions: "none, curl, dom, json, mbstring, tokenizer, xml, xmlwriter, iconv"
           php-version: "${{ matrix.php-version }}"

       - name: Use Node.js ${{ matrix.node-version }}
diff --git a/ChangeLog-8.php b/ChangeLog-8.php
index cbce359757..0e038fa5b7 100644
--- a/ChangeLog-8.php
+++ b/ChangeLog-8.php
@@ -9,6 +9,112 @@

<a id="PHP_8_4"></a>

+<section class="version" id="8.4.10"><!-- {{{ 8.4.10 -->
+<h3>Version 8.4.10</h3>
+<b><?php release_date('03-Jul-2025'); ?></b>
+<ul><li>BcMath:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 18641); ?> (Accessing a BcMath\Number property by ref crashes).</li>
+</ul></li>
+<li>Core:
+<ul>
+ <li>Fixed bugs <?php githubissuel('php/php-src', 17711); ?> and <?php githubissuel('php/php-src', 18022); ?> (Infinite recursion on deprecated attribute evaluation) and <?php githubissuel('php/php-src', 18464); ?> (Recursion protection for deprecation constants not released on bailout).</li>
+ <li>Fixed <?php githubissuel('php/php-src', 18695); ?> (zend_ast_export() - float number is not preserved).</li>
+ <li>Fix handling of references in zval_try_get_long().</li>
+ <li>Do not delete main chunk in zend_gc.</li>
+ <li>Fix compile issues with zend_alloc and some non-default options.</li>
+</ul></li>
+<li>Curl:
+<ul>
+ <li>Fix memory leak when setting a list via curl_setopt fails.</li>
+</ul></li>
+<li>Date:
+<ul>
+ <li>Fix leaks with multiple calls to DatePeriod iterator current().</li>
+</ul></li>
+<li>DOM:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 18744); ?> (classList works not correctly if copy HTMLElement by clone keyword).</li>
+</ul></li>
+<li>FPM:
+<ul>
+ <li>Fixed <?php githubissuel('php/php-src', 18662); ?> (fpm_get_status segfault).</li>
+</ul></li>
+<li>Hash:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 14551); ?> (PGO build fails with xxhash).</li>
+</ul></li>
+<li>Intl:
+<ul>
+ <li>Fix memory leak in intl_datetime_decompose() on failure.</li>
+ <li>Fix memory leak in locale lookup on failure.</li>
+</ul></li>
+<li>Opcache:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 18743); ?> (Incompatibility in Inline TLS Assembly on Alpine 3.22).</li>
+</ul></li>
+<li>ODBC:
+<ul>
+ <li>Fix memory leak on php_odbc_fetch_hash() failure.</li>
+</ul></li>
+<li>OpenSSL:
+<ul>
+ <li>Fix memory leak of X509_STORE in php_openssl_setup_verify() on failure.</li>
+ <li><?php bugfix(74796); ?> (Requests through http proxy set peer name).</li>
+</ul></li>
+<li>PGSQL:
+<ul>
+ <li>Fixed <?php githubsecurityl('php/php-src', 'hrwm-9436-5mv3'); ?> (pgsql extension does not check for errors during escaping). (CVE-2025-1735)</li>
+ <li>Fix warning not being emitted when failure to cancel a query with pg_cancel_query().</li>
+</ul></li>
+<li>PDO ODBC:
+<ul>
+ <li>Fix memory leak if WideCharToMultiByte() fails.</li>
+</ul></li>
+<li>PDO Sqlite:
+<ul>
+ <li>Fixed memory leak with Pdo_Sqlite::createCollation when the callback has an incorrect return type.</li>
+</ul></li>
+<li>Phar:
+<ul>
+ <li>Add missing filter cleanups on phar failure.</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 18642); ?> (Signed integer overflow in ext/phar fseek).</li>
+</ul></li>
+<li>PHPDBG:
+<ul>
+ <li>Fix 'phpdbg --help' segfault on shutdown with USE_ZEND_ALLOC=0.</li>
+</ul></li>
+<li>Random:
+<ul>
+ <li>Fix reference type confusion and leak in user random engine.</li>
+</ul></li>
+<li>Readline:
+<ul>
+ <li>Fix memory leak when calloc() fails in php_readline_completion_cb().</li>
+</ul></li>
+<li>SimpleXML:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 18597); ?> (Heap-buffer-overflow in zend_alloc.c when assigning string with UTF-8 bytes).</li>
+</ul></li>
+<li>SOAP:
+<ul>
+ <li>Fix memory leaks in php_http.c when call_user_function() fails.</li>
+ <li>Fixed <?php githubsecurityl('php/php-src', '453j-q27h-5p8x'); ?> (NULL Pointer Dereference in PHP SOAP Extension via Large XML Namespace Prefix). (CVE-2025-6491)</li>
+</ul></li>
+<li>Standard:
+<ul>
+ <li>Fixed <?php githubsecurityl('php/php-src', '3cr5-j632-f35r'); ?> (Null byte termination in hostnames). (CVE-2025-1220)</li>
+</ul></li>
+<li>Tidy:
+<ul>
+ <li>Fix memory leak in tidy output handler on error.</li>
+ <li>Fix tidyOptIsReadonly deprecation, using tidyOptGetCategory.</li>
+</ul></li>
+</ul>
+<!-- }}} --></section>
+
+
+
<section class="version" id="8.4.8"><!-- {{{ 8.4.8 -->
<h3>Version 8.4.8</h3>
<b><?php release_date('05-Jun-2025'); ?></b>
@@ -1249,6 +1355,95 @@

<a id="PHP_8_3"></a>

+<section class="version" id="8.3.23"><!-- {{{ 8.3.23 -->
+<h3>Version 8.3.23</h3>
+<b><?php release_date('03-Jul-2025'); ?></b>
+<ul><li>Core:
+<ul>
+ <li>Fixed <?php githubissuel('php/php-src', 18695); ?> (zend_ast_export() - float number is not preserved).</li>
+ <li>Do not delete main chunk in zend_gc.</li>
+ <li>Fix compile issues with zend_alloc and some non-default options.</li>
+</ul></li>
+<li>Curl:
+<ul>
+ <li>Fix memory leak when setting a list via curl_setopt fails.</li>
+ <li>Fix incorrect OpenSSL version detection.</li>
+</ul></li>
+<li>Date:
+<ul>
+ <li>Fix leaks with multiple calls to DatePeriod iterator current().</li>
+</ul></li>
+<li>FPM:
+<ul>
+ <li>Fixed <?php githubissuel('php/php-src', 18662); ?> (fpm_get_status segfault).</li>
+</ul></li>
+<li>Hash:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 14551); ?> (PGO build fails with xxhash).</li>
+</ul></li>
+<li>Intl:
+<ul>
+ <li>Fix memory leak in intl_datetime_decompose() on failure.</li>
+ <li>Fix memory leak in locale lookup on failure.</li>
+</ul></li>
+<li>ODBC:
+<ul>
+ <li>Fix memory leak on php_odbc_fetch_hash() failure.</li>
+</ul></li>
+<li>Opcache:
+<ul>
+ <li>Fixed bug <?php githubissuel('php/php-src', 18743); ?> (Incompatibility in Inline TLS Assembly on Alpine 3.22).</li>
+</ul></li>
+<li>OpenSSL:
+<ul>
+ <li>Fix memory leak of X509_STORE in php_openssl_setup_verify() on failure.</li>
+ <li><?php bugfix(74796); ?> (Requests through http proxy set peer name).</li>
+</ul></li>
+<li>PGSQL:
+<ul>
+ <li>Fixed <?php githubsecurityl('php/php-src', 'hrwm-9436-5mv3'); ?> (pgsql extension does not check for errors during escaping). (CVE-2025-1735)</li>
+ <li>Fix warning not being emitted when failure to cancel a query with pg_cancel_query().</li>
+</ul></li>
+<li>Phar:
+<ul>
+ <li>Add missing filter cleanups on phar failure.</li>
+ <li>Fixed bug <?php githubissuel('php/php-src', 18642); ?> (Signed integer overflow in ext/phar fseek).</li>
+</ul></li>
+<li>PHPDBG:
+<ul>
+ <li>Fix 'phpdbg --help' segfault on shutdown with USE_ZEND_ALLOC=0.</li>
+</ul></li>
+<li>PDO ODBC:
+<ul>
+ <li>Fix memory leak if WideCharToMultiByte() fails.</li>
+</ul></li>
+<li>Random:
+<ul>
+ <li>Fix reference type confusion and leak in user random engine.</li>
+</ul></li>
+<li>Readline:
+<ul>
+ <li>Fix memory leak when calloc() fails in php_readline_completion_cb().</li>
+</ul></li>
+<li>SOAP:
+<ul>
+ <li>Fix memory leaks in php_http.c when call_user_function() fails.</li>
+ <li>Fixed <?php githubsecurityl('php/php-src', '453j-q27h-5p8x'); ?> (NULL Pointer Dereference in PHP SOAP Extension via Large XML Namespace Prefix). (CVE-2025-6491)</li>
+</ul></li>
+<li>Standard:
+<ul>
+ <li>Fixed <?php githubsecurityl('php/php-src', '3cr5-j632-f35r'); ?> (Null byte termination in hostnames). (CVE-2025-1220)</li>
+</ul></li>
+<li>Tidy:
+<ul>
+ <li>Fix memory leak in tidy output handler on error.</li>
+ <li>Fix tidyOptIsReadonly deprecation, using tidyOptGetCategory.</li>
+</ul></li>
+</ul>
+<!-- }}} --></section>
+
+
+
<section class="version" id="8.3.22"><!-- {{{ 8.3.22 -->
<h3>Version 8.3.22</h3>
<b><?php release_date('05-Jun-2025'); ?></b>
@@ -3228,6 +3423,26 @@

<a id="PHP_8_2"></a>

+<section class="version" id="8.2.29"><!-- {{{ 8.2.29 -->
+<h3>Version 8.2.29</h3>
+<b><?php release_date('03-Jul-2025'); ?></b>
+<ul><li>PGSQL:
+<ul>
+ <li>Fixed <?php githubsecurityl('php/php-src', 'hrwm-9436-5mv3'); ?> (pgsql extension does not check for errors during escaping). (CVE-2025-1735)</li>
+</ul></li>
+<li>SOAP:
+<ul>
+ <li>Fixed <?php githubsecurityl('php/php-src', '453j-q27h-5p8x'); ?> (NULL Pointer Dereference in PHP SOAP Extension via Large XML Namespace Prefix). (CVE-2025-6491)</li>
+</ul></li>
+<li>Standard:
+<ul>
+ <li>Fixed <?php githubsecurityl('php/php-src', '3cr5-j632-f35r'); ?> (Null byte termination in hostnames). (CVE-2025-1220)</li>
+</ul></li>
+</ul>
+<!-- }}} --></section>
+
+
+
<section class="version" id="8.2.28"><!-- {{{ 8.2.28 -->
<h3>Version 8.2.28</h3>
<b><?php release_date('13-Mar-2025'); ?></b>
@@ -5745,6 +5960,26 @@

<a id="PHP_8_1"></a>

+<section class="version" id="8.1.33"><!-- {{{ 8.1.33 -->
+<h3>Version 8.1.33</h3>
+<b><?php release_date('03-Jul-2025'); ?></b>
+<ul><li>PGSQL:
+<ul>
+ <li>Fixed <?php githubsecurityl('php/php-src', 'hrwm-9436-5mv3'); ?> (pgsql extension does not check for errors during escaping). (CVE-2025-1735)</li>
+</ul></li>
+<li>SOAP:
+<ul>
+ <li>Fixed <?php githubsecurityl('php/php-src', '453j-q27h-5p8x'); ?> (NULL Pointer Dereference in PHP SOAP Extension via Large XML Namespace Prefix). (CVE-2025-6491)</li>
+</ul></li>
+<li>Standard:
+<ul>
+ <li>Fixed <?php githubsecurityl('php/php-src', '3cr5-j632-f35r'); ?> (Null byte termination in hostnames). (CVE-2025-1220)</li>
+</ul></li>
+</ul>
+<!-- }}} --></section>
+
+
+
<section class="version" id="8.1.32"><!-- {{{ 8.1.32 -->
<h3>Version 8.1.32</h3>
<b><?php release_date('13-Mar-2025'); ?></b>
diff --git a/archive/2013.php b/archive/2013.php
index a6a745885b..744b8dd584 100644
--- a/archive/2013.php
+++ b/archive/2013.php
@@ -2,7 +2,6 @@

$_SERVER['BASE_PAGE'] = 'archive/2013.php';
include_once __DIR__ . '/../include/prepend.inc';
-include_once __DIR__ . '/../include/pregen-news.inc';
news_archive_sidebar();
site_header("News Archive - 2013", ["cache" => true]);
?>
diff --git a/archive/2014.php b/archive/2014.php
index e5d456aef2..7a61874b99 100644
--- a/archive/2014.php
+++ b/archive/2014.php
@@ -2,7 +2,6 @@

$_SERVER['BASE_PAGE'] = 'archive/2014.php';
include_once __DIR__ . '/../include/prepend.inc';
-include_once __DIR__ . '/../include/pregen-news.inc';
news_archive_sidebar();
site_header("News Archive - 2014", ["cache" => true]);
?>
diff --git a/archive/2015.php b/archive/2015.php
index b42a3dcef5..b71a865e4b 100644
--- a/archive/2015.php
+++ b/archive/2015.php
@@ -1,8 +1,9 @@
<?php

+use phpweb\News\NewsHandler;
+
$_SERVER['BASE_PAGE'] = 'archive/2015.php';
include_once __DIR__ . '/../include/prepend.inc';
-include_once __DIR__ . '/../include/pregen-news.inc';
news_archive_sidebar();
site_header("News Archive - 2015");
?>
@@ -17,7 +18,7 @@

<?php

-print_news($NEWS_ENTRIES, ["conferences", "cfp", "frontpage", "nofrontpage"], 500, 2015);
+print_news((new NewsHandler())->getNewsByYear(2015), ["conferences", "cfp", "frontpage", "nofrontpage"], 500);

/* %s/<a href="\(.*\)"><img src="\/images\/news\/\(.*\)" alt="\(.*\)" width.*><\/a>/<?php news_image("\1", "\2", "\3"); ?>/g */
site_footer(['elephpants' => true, 'sidebar' => $SIDEBAR_DATA]);
diff --git a/archive/2016.php b/archive/2016.php
index 10e482cec7..228f0ea9a2 100644
--- a/archive/2016.php
+++ b/archive/2016.php
@@ -1,8 +1,9 @@
<?php

+use phpweb\News\NewsHandler;
+
$_SERVER['BASE_PAGE'] = 'archive/2016.php';
include_once __DIR__ . '/../include/prepend.inc';
-include_once __DIR__ . '/../include/pregen-news.inc';
news_archive_sidebar();
site_header("News Archive - 2016");
?>
@@ -17,7 +18,7 @@

<?php

-print_news($NEWS_ENTRIES, ["conferences", "cfp", "frontpage", "nofrontpage"], 500, 2016);
+print_news((new NewsHandler())->getNewsByYear(2016), ["conferences", "cfp", "frontpage", "nofrontpage"], 500);

/* %s/<a href="\(.*\)"><img src="\/images\/news\/\(.*\)" alt="\(.*\)" width.*><\/a>/<?php news_image("\1", "\2", "\3"); ?>/g */
site_footer(['elephpants' => true, 'sidebar' => $SIDEBAR_DATA]);
diff --git a/archive/2017.php b/archive/2017.php
index f49960fc1b..26e7b5a400 100644
--- a/archive/2017.php
+++ b/archive/2017.php
@@ -1,8 +1,9 @@
<?php

+use phpweb\News\NewsHandler;
+
$_SERVER['BASE_PAGE'] = 'archive/2017.php';
include_once __DIR__ . '/../include/prepend.inc';
-include_once __DIR__ . '/../include/pregen-news.inc';
news_archive_sidebar();
site_header("News Archive - 2017");
?>
@@ -17,7 +18,7 @@

<?php

-print_news($NEWS_ENTRIES, null, 500, 2017);
+print_news((new NewsHandler())->getNewsByYear(2017), null, 500);

/* %s/<a href="\(.*\)"><img src="\/images\/news\/\(.*\)" alt="\(.*\)" width.*><\/a>/<?php news_image("\1", "\2", "\3"); ?>/g */
site_footer(['elephpants' => true, 'sidebar' => $SIDEBAR_DATA]);
diff --git a/archive/2018.php b/archive/2018.php
index 7a9a74989c..1db8020b7b 100644
--- a/archive/2018.php
+++ b/archive/2018.php
@@ -1,8 +1,9 @@
<?php

+use phpweb\News\NewsHandler;
+
$_SERVER['BASE_PAGE'] = 'archive/2018.php';
include_once __DIR__ . '/../include/prepend.inc';
-include_once __DIR__ . '/../include/pregen-news.inc';
news_archive_sidebar();
site_header("News Archive - 2018");
?>
@@ -17,7 +18,7 @@

<?php

-print_news($NEWS_ENTRIES, null, 500, 2018);
+print_news((new NewsHandler())->getNewsByYear(2018), null, 500);

/* %s/<a href="\(.*\)"><img src="\/images\/news\/\(.*\)" alt="\(.*\)" width.*><\/a>/<?php news_image("\1", "\2", "\3"); ?>/g */
site_footer(['elephpants' => true, 'sidebar' => $SIDEBAR_DATA]);
diff --git a/archive/2019.php b/archive/2019.php
index 9e6d3ad3fb..3538aa2daa 100644
--- a/archive/2019.php
+++ b/archive/2019.php
@@ -1,8 +1,9 @@
<?php

+use phpweb\News\NewsHandler;
+
$_SERVER['BASE_PAGE'] = 'archive/2019.php';
include_once __DIR__ . '/../include/prepend.inc';
-include_once __DIR__ . '/../include/pregen-news.inc';
news_archive_sidebar();
site_header("News Archive - 2019");
?>
@@ -17,7 +18,7 @@

<?php

-print_news($NEWS_ENTRIES, null, 500, 2019);
+print_news((new NewsHandler())->getNewsByYear(2019), null, 500);

/* %s/<a href="\(.*\)"><img src="\/images\/news\/\(.*\)" alt="\(.*\)" width.*><\/a>/<?php news_image("\1", "\2", "\3"); ?>/g */
site_footer(['elephpants' => true, 'sidebar' => $SIDEBAR_DATA]);
diff --git a/archive/2020.php b/archive/2020.php
index ab66d3c0ea..5a469f6cc9 100644
--- a/archive/2020.php
+++ b/archive/2020.php
@@ -1,8 +1,9 @@
<?php

+use phpweb\News\NewsHandler;
+
$_SERVER['BASE_PAGE'] = 'archive/2020.php';
include_once __DIR__ . '/../include/prepend.inc';
-include_once __DIR__ . '/../include/pregen-news.inc';
news_archive_sidebar();
site_header("News Archive - 2020");
?>
@@ -17,7 +18,7 @@

<?php

-print_news($NEWS_ENTRIES, null, 500, 2020);
+print_news((new NewsHandler())->getNewsByYear(2020), null, 500);

/* %s/<a href="\(.*\)"><img src="\/images\/news\/\(.*\)" alt="\(.*\)" width.*><\/a>/<?php news_image("\1", "\2", "\3"); ?>/g */
site_footer(['elephpants' => true, 'sidebar' => $SIDEBAR_DATA]);
diff --git a/archive/2021.php b/archive/2021.php
index 6a57771c18..1191c7585b 100644
--- a/archive/2021.php
+++ b/archive/2021.php
@@ -1,8 +1,9 @@
<?php

+use phpweb\News\NewsHandler;
+
$_SERVER['BASE_PAGE'] = 'archive/2021.php';
include_once __DIR__ . '/../include/prepend.inc';
-include_once __DIR__ . '/../include/pregen-news.inc';
news_archive_sidebar();
site_header("News Archive - 2021");
?>
@@ -17,7 +18,7 @@

<?php

-print_news($NEWS_ENTRIES, null, 500, 2021);
+print_news((new NewsHandler())->getNewsByYear(2021), null, 500);

/* %s/<a href="\(.*\)"><img src="\/images\/news\/\(.*\)" alt="\(.*\)" width.*><\/a>/<?php news_image("\1", "\2", "\3"); ?>/g */
site_footer(['elephpants' => true, 'sidebar' => $SIDEBAR_DATA]);
diff --git a/archive/2022.php b/archive/2022.php
index 34a16adefc..abfcee9354 100644
--- a/archive/2022.php
+++ b/archive/2022.php
@@ -1,8 +1,9 @@
<?php

+use phpweb\News\NewsHandler;
+
$_SERVER['BASE_PAGE'] = 'archive/2022.php';
include_once __DIR__ . '/../include/prepend.inc';
-include_once __DIR__ . '/../include/pregen-news.inc';
news_archive_sidebar();
site_header("News Archive - 2022");
?>
@@ -17,5 +18,5 @@

<?php

-print_news($NEWS_ENTRIES, null, 500, 2022);
+print_news((new NewsHandler())->getNewsByYear(2022), null, 500);
site_footer(['elephpants' => true, 'sidebar' => $SIDEBAR_DATA]);
diff --git a/archive/2023.php b/archive/2023.php
index 706530a7ce..b6ef8abde9 100644
--- a/archive/2023.php
+++ b/archive/2023.php
@@ -1,8 +1,9 @@
<?php

+use phpweb\News\NewsHandler;
+
$_SERVER['BASE_PAGE'] = 'archive/2023.php';
include_once __DIR__ . '/../include/prepend.inc';
-include_once __DIR__ . '/../include/pregen-news.inc';
news_archive_sidebar();
site_header("News Archive - 2023");
?>
@@ -17,5 +18,5 @@

<?php

-print_news($NEWS_ENTRIES, null, 500, 2023);
+print_news((new NewsHandler())->getNewsByYear(2023), null, 500);
site_footer(['elephpants' => true, 'sidebar' => $SIDEBAR_DATA]);
diff --git a/archive/2024.php b/archive/2024.php
index 43a145ae57..9834117665 100644
--- a/archive/2024.php
+++ b/archive/2024.php
@@ -1,8 +1,9 @@
<?php

+use phpweb\News\NewsHandler;
+
$_SERVER['BASE_PAGE'] = 'archive/2024.php';
include_once __DIR__ . '/../include/prepend.inc';
-include_once __DIR__ . '/../include/pregen-news.inc';
news_archive_sidebar();
site_header("News Archive - 2024");
?>
@@ -17,5 +18,5 @@

<?php

-print_news($NEWS_ENTRIES, null, 500, 2024);
+print_news((new NewsHandler())->getNewsByYear(2024), null, 500);
site_footer(['elephpants' => true, 'sidebar' => $SIDEBAR_DATA]);
diff --git a/archive/2025.php b/archive/2025.php
index abbb2f1e0a..2787ee7d73 100644
--- a/archive/2025.php
+++ b/archive/2025.php
@@ -1,8 +1,9 @@
<?php

+use phpweb\News\NewsHandler;
+
$_SERVER['BASE_PAGE'] = 'archive/2025.php';
include_once __DIR__ . '/../include/prepend.inc';
-include_once __DIR__ . '/../include/pregen-news.inc';
news_archive_sidebar();
site_header("News Archive - 2025");
?>
@@ -17,5 +18,5 @@

<?php

-print_news($NEWS_ENTRIES, null, 500, 2025);
+print_news((new NewsHandler())->getNewsByYear(2025), null, 500);
site_footer(['elephpants' => true, 'sidebar' => $SIDEBAR_DATA]);
diff --git a/archive/archive.xml b/archive/archive.xml
index 903c06a155..54c22a8410 100644
--- a/archive/archive.xml
+++ b/archive/archive.xml
@@ -9,6 +9,14 @@
     <uri>PHP: Manual Quick Reference;
     <email>php-webmaster@lists.php.net</email>
   </author>
+ <xi:include href="entries/2025-07-17-1.xml"/>
+ <xi:include href="entries/2025-07-03-5.xml"/>
+ <xi:include href="entries/2025-07-03-4.xml"/>
+ <xi:include href="entries/2025-07-03-3.xml"/>
+ <xi:include href="entries/2025-07-03-2.xml"/>
+ <xi:include href="entries/2025-07-03-1.xml"/>
+ <xi:include href="entries/2025-06-11-1.xml"/>
+ <xi:include href="entries/2025-06-09-1.xml"/>
   <xi:include href="entries/2025-06-06-1.xml"/>
   <xi:include href="entries/2025-06-05-2.xml"/>
   <xi:include href="entries/2025-06-05-1.xml"/>
diff --git a/archive/entries/2025-06-09-1.xml b/archive/entries/2025-06-09-1.xml
new file mode 100644
index 0000000000..c2e56258c8
--- /dev/null
+++ b/archive/entries/2025-06-09-1.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom&quot; xmlns:default="PHP: Manual Quick Reference;
+ <title>Longhorn PHP 2025 - Call For Papers</title>
+ <id>PHP: News Archive - 2025;
+ <published>2025-06-09T12:50:54+00:00</published>
+ <updated>2025-06-09T12:50:54+00:00</updated>
+ <link href="PHP: PHP Conferences around the world; rel="alternate" type="text/html"/>
+ <link href="https://cfp.longhornphp.com" rel="via" type="text/html"/>
+ <default:finalTeaserDate xmlns="http://php.net/ns/news&quot;&gt;2025\-07\-18&lt;/default:finalTeaserDate&gt;
+ <category term="cfp" label="Call for Papers"/>
+ <default:newsImage xmlns="PHP: Manual Quick Reference; link="https://cfp.longhornphp.com" title="Longhorn PHP">longhornphp.png</default:newsImage>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml&quot;&gt;
+ <p>Longhorn PHP returns for 2025! Held in Austin, TX, the conference will run from October 23-25, with a tutorial day on Thursday, followed by two main conference days. We are excited to bring PHP developers from all backgrounds together again for three days of fun and education. <a href="https://cfp.longhornphp.com/&quot;&gt;We are currently accepting talk and tutorial submissions.</a> While the CFP is open, we also have our Blind Bird tickets available for sale.</p>
+ <p><a href="https://www.longhornphp.com/&quot;&gt;Register today!</a></p>
+ <p>Follow us on <a href="https://phpc.social/@longhorn&quot;&gt;Mastodon&lt;/a&gt; signup for emails at <a href="https://www.longhornphp.com/&quot;&gt;longhornphp\.com&lt;/a&gt; to get notified with important conference updates.</p>
+ </div>
+ </content>
+</entry>
diff --git a/archive/entries/2025-06-11-1.xml b/archive/entries/2025-06-11-1.xml
new file mode 100644
index 0000000000..1b0f181eba
--- /dev/null
+++ b/archive/entries/2025-06-11-1.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom&quot; xmlns:default="PHP: Manual Quick Reference;
+ <title>CakeFest 2025 Madrid: The Official CakePHP Conference</title>
+ <id>PHP: News Archive - 2025;
+ <published>2025-06-11T09:44:39+00:00</published>
+ <updated>2025-06-11T09:44:39+00:00</updated>
+ <link href="PHP: PHP Conferences around the world; rel="alternate" type="text/html"/>
+ <link href="https://cakefest.org/&quot; rel="via" type="text/html"/>
+ <default:finalTeaserDate xmlns="http://php.net/ns/news&quot;&gt;2025\-10\-09&lt;/default:finalTeaserDate&gt;
+ <category term="conferences" label="Conference announcement"/>
+ <default:newsImage xmlns="PHP: Manual Quick Reference; link="https://cakefest.org/&quot; title="CakeFest 2025 Madrid">cakefest-2017.png</default:newsImage>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml&quot;&gt;
+ <p>
+ CakeFest is the official conference dedicated to the <b>CakePHP</b> framework and community. Whether
+ you're a seasoned developer or just starting out,
+ CakeFest offers two days of workshops, talks, networking, and learning from top contributors and
+ professionals in the <b>CakePHP</b> ecosystem.
+ </p>
+
+ <p>
+ In 2025, we’re celebrating 20 years of <b>CakePHP</b> - a major milestone in open-source history!
+ </p>
+ <p>
+ Quick links:
+ </p>
+ <ul>
+ <li>
+ <a href="https://cakefest.org/schedule&quot;&gt;CakeFest 2025 Schedule</a>
+ </li>
+ <li>
+ <a href="https://cakefest.org/tickets&quot;&gt;Get your CakeFest ticket</a>
+ </li>
+ </ul>
+ <p>
+ Join us in Madrid for this special anniversary edition
+ of CakeFest: connect with fellow developers, discover the latest in <b>CakePHP</b>, and enjoy an
+ unforgettable community experience.
+ </p>
+ </div>
+ </content>
+</entry>
diff --git a/archive/entries/2025-07-03-1.xml b/archive/entries/2025-07-03-1.xml
new file mode 100644
index 0000000000..871374ace1
--- /dev/null
+++ b/archive/entries/2025-07-03-1.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom&quot;&gt;
+ <title>PHP 8.4.10 Released!</title>
+ <id>PHP: News Archive - 2025;
+ <published>2025-07-03T11:44:39+00:00</published>
+ <updated>2025-07-03T11:44:39+00:00</updated>
+ <link href="PHP: Hypertext Preprocessor; rel="alternate" type="text/html"/>
+ <link href="PHP: News Archive - 2025; rel="via" type="text/html"/>
+ <category term="releases" label="New PHP release"/>
+ <category term="frontpage" label="PHP.net frontpage news"/>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;The PHP development team announces the immediate availability of PHP 8.4.10. This is a security release.</p>
+
+<p>Version 8.4.9 was skipped because it was tagged without including security patches.</p>
+<p>All PHP 8.4 users are encouraged to upgrade to this version.</p>
+
+<p>For source downloads of PHP 8.4.10 please visit our <a href="PHP: Manual Quick Reference page</a>,
+Windows source and binaries can be found on <a href="https://windows.php.net/download/&quot;&gt;windows\.php\.net/download/&lt;/a&gt;\.
+The list of changes is recorded in the <a href="PHP: PHP 8 ChangeLog.
+</p> </div>
+ </content>
+</entry>
diff --git a/archive/entries/2025-07-03-2.xml b/archive/entries/2025-07-03-2.xml
new file mode 100644
index 0000000000..e545101462
--- /dev/null
+++ b/archive/entries/2025-07-03-2.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom&quot;&gt;
+ <title>PHP 8.2.29 Released!</title>
+ <id>PHP: News Archive - 2025;
+ <published>2025-07-03T12:03:57+00:00</published>
+ <updated>2025-07-03T12:03:57+00:00</updated>
+ <link href="PHP: Hypertext Preprocessor; rel="alternate" type="text/html"/>
+ <link href="PHP: News Archive - 2025; rel="via" type="text/html"/>
+ <category term="releases" label="New PHP release"/>
+ <category term="frontpage" label="PHP.net frontpage news"/>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;The PHP development team announces the immediate availability of PHP 8.2.29. This is a security release.</p>
+
+<p>All PHP 8.2 users are encouraged to upgrade to this version.</p>
+
+<p>For source downloads of PHP 8.2.29 please visit our <a href="PHP: Manual Quick Reference page</a>,
+Windows source and binaries can be found on <a href="https://windows.php.net/download/&quot;&gt;windows\.php\.net/download/&lt;/a&gt;\.
+The list of changes is recorded in the <a href="PHP: PHP 8 ChangeLog.
+</p> </div>
+ </content>
+</entry>
diff --git a/archive/entries/2025-07-03-3.xml b/archive/entries/2025-07-03-3.xml
new file mode 100644
index 0000000000..69519dc097
--- /dev/null
+++ b/archive/entries/2025-07-03-3.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom&quot;&gt;
+ <title>PHP 8.1.33 Released!</title>
+ <id>PHP: News Archive - 2025;
+ <published>2025-07-03T14:35:29+00:00</published>
+ <updated>2025-07-03T14:35:29+00:00</updated>
+ <link href="PHP: Hypertext Preprocessor; rel="alternate" type="text/html"/>
+ <link href="PHP: News Archive - 2025; rel="via" type="text/html"/>
+ <category term="releases" label="New PHP release"/>
+ <category term="frontpage" label="PHP.net frontpage news"/>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;The PHP development team announces the immediate availability of PHP 8.1.33. This is a security release.</p>
+
+<p>All PHP 8.1 users are encouraged to upgrade to this version.</p>
+
+<p>For source downloads of PHP 8.1.33 please visit our <a href="PHP: Manual Quick Reference page</a>,
+Windows source and binaries can be found on <a href="https://windows.php.net/download/&quot;&gt;windows\.php\.net/download/&lt;/a&gt;\.
+The list of changes is recorded in the <a href="PHP: PHP 8 ChangeLog.
+</p> </div>
+ </content>
+</entry>
diff --git a/archive/entries/2025-07-03-4.xml b/archive/entries/2025-07-03-4.xml
new file mode 100644
index 0000000000..ac1f7e26dc
--- /dev/null
+++ b/archive/entries/2025-07-03-4.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom&quot;&gt;
+ <title>PHP 8.3.23 Released!</title>
+ <id>https://www.php.net/archive/2025.php#2025-07-03-4&lt;/id&gt;
+ <published>2025-07-03T15:24:35+00:00</published>
+ <updated>2025-07-03T15:24:35+00:00</updated>
+ <link href="https://www.php.net/index.php#2025-07-03-4&quot; rel="alternate" type="text/html"/>
+ <link href="https://www.php.net/archive/2025.php#2025-07-03-4&quot; rel="via" type="text/html"/>
+ <category term="releases" label="New PHP release"/>
+ <category term="frontpage" label="PHP.net frontpage news"/>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;The PHP development team announces the immediate availability of PHP 8.3.23. This is a security release.</p>
+
+<p>All PHP 8.3 users are encouraged to upgrade to this version.</p>
+
+<p>For source downloads of PHP 8.3.23 please visit our <a href="PHP: Manual Quick Reference page</a>,
+Windows source and binaries can be found on <a href="https://windows.php.net/download/&quot;&gt;windows\.php\.net/download/&lt;/a&gt;\.
+The list of changes is recorded in the <a href="https://www.php.net/ChangeLog-8.php#8.3.23&quot;&gt;ChangeLog&lt;/a&gt;\.
+</p> </div>
+ </content>
+</entry>
diff --git a/archive/entries/2025-07-03-5.xml b/archive/entries/2025-07-03-5.xml
new file mode 100644
index 0000000000..f6a035ec2c
--- /dev/null
+++ b/archive/entries/2025-07-03-5.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom&quot;&gt;
+ <title>PHP 8.5.0 Alpha 1 available for testing</title>
+ <id>https://www.php.net/archive/2025.php#2025-07-03-5&lt;/id&gt;
+ <published>2025-07-03T17:59:40+00:00</published>
+ <updated>2025-07-03T17:59:40+00:00</updated>
+ <link href="https://www.php.net/index.php#2025-07-03-5&quot; rel="alternate" type="text/html"/>
+ <link href="https://www.php.net/archive/2025.php#2025-07-03-5&quot; rel="via" type="text/html"/>
+ <category term="frontpage" label="PHP.net frontpage news"/>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml&quot;&gt;
+ <p>The PHP team is pleased to announce the first testing release of PHP 8.5.0, Alpha 1. This starts the PHP 8.5 release cycle, the rough outline of which is specified in the <a href="https://wiki.php.net/todo/php85&quot;&gt;PHP Wiki</a>.</p>
+ <p>For source downloads of PHP 8.5.0 Alpha 1 please visit the <a href="https://downloads.php.net/~daniels/&quot;&gt;download page</a>.</p>
+ <p>Please carefully test this version and report any issues found <a href="https://github.com/php/php-src/issues/new?template=bug_report.yml&quot;&gt;on GitHub</a>.</p>
+ <p><strong>Please DO NOT use this version in production, it is an early test version.</strong></p>
+ <p>For more information on the new features and other changes, you can read the <a href="https://github.com/php/php-src/blob/php-8.5.0alpha1/NEWS&quot;&gt;NEWS&lt;/a&gt; file, or the <a href="https://github.com/php/php-src/blob/php-8.5.0alpha1/UPGRADING&quot;&gt;UPGRADING&lt;/a&gt; file for a complete list of upgrading notes. These files can also be found in the release archive.</p>
+ <p>The next release will be Alpha 2, planned for 17 Jul 2025.</p>
+ <p>The signatures for the release can be found in the <a href="https://gist.github.com/DanielEScherzer/34f32cb39e432134d77c618642972b84&quot;&gt;manifest&lt;/a&gt; or on the <a href="https://www.php.net/release-candidates.php&quot;&gt;Release Candidates page</a>.</p>
+ <p>Thank you for helping us make PHP better.</p>
+ </div>
+ </content>
+</entry>
diff --git a/archive/entries/2025-07-17-1.xml b/archive/entries/2025-07-17-1.xml
new file mode 100644
index 0000000000..7e8bc9f616
--- /dev/null
+++ b/archive/entries/2025-07-17-1.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom&quot; xmlns:default="http://www.w3.org/1999/xhtml&quot;&gt;
+ <title>PHP 8.5.0 Alpha 2 available for testing</title>
+ <id>https://www.php.net/archive/2025.php#2025-07-17-1&lt;/id&gt;
+ <published>2025-07-17T11:45:54+00:00</published>
+ <updated>2025-07-17T11:45:54+00:00</updated>
+ <link href="https://www.php.net/index.php#2025-07-17-1&quot; rel="alternate" type="text/html"/>
+ <link href="https://www.php.net/archive/2025.php#2025-07-17-1&quot; rel="via" type="text/html"/>
+ <category term="frontpage" label="PHP.net frontpage news"/>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml&quot;&gt;
+ <p>The PHP team is pleased to announce the second testing release of PHP 8.5.0, Alpha 2. This continues the PHP 8.5 release cycle, the rough outline of which is specified in the <a href="https://wiki.php.net/todo/php85&quot;&gt;PHP Wiki</a>.</p>
+ <p>For source downloads of PHP 8.5.0 Alpha 2 please visit the <a href="https://downloads.php.net/~edorian/&quot;&gt;download page</a>.</p>
+ <p>Please carefully test this version and report any issues found <a href="https://github.com/php/php-src/issues/new?template=bug_report.yml&quot;&gt;on GitHub</a>.</p>
+ <p><strong>Please DO NOT use this version in production, it is an early test version.</strong></p>
+ <p>For more information on the new features and other changes, you can read the <a href="https://github.com/php/php-src/blob/php-8.5.0alpha2/NEWS&quot;&gt;NEWS&lt;/a&gt; file, or the <a href="https://github.com/php/php-src/blob/php-8.5.0alpha2/UPGRADING&quot;&gt;UPGRADING&lt;/a&gt; file for a complete list of upgrading notes. These files can also be found in the release archive.</p>
+ <p>The next release will be Alpha 3, planned for 31 Jul 2025.</p>
+ <p>The signatures for the release can be found in the <a href="https://gist.github.com/edorian/be165326301ab2b6b0bf18bb88123fa0&quot;&gt;manifest&lt;/a&gt; or on the <a href="https://www.php.net/release-candidates.php&quot;&gt;Release Candidates page</a>.</p>
+ <p>Thank you for helping us make PHP better.</p>
+ </div>
+ </content>
+</entry>
diff --git a/composer.json b/composer.json
index 4732dc6ae2..0d150ea6ec 100644
--- a/composer.json
+++ b/composer.json
@@ -12,7 +12,7 @@
     },
     "require-dev": {
         "ext-curl": "*",
- "friendsofphp/php-cs-fixer": "^3.75.0",
+ "friendsofphp/php-cs-fixer": "^3.84.0",
         "phpunit/phpunit": "^11.5.6"
     },
     "autoload": {
diff --git a/composer.lock b/composer.lock
index c6a99c0233..dbecaa42d4 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies&quot;,
         "This file is @generated automatically"
     ],
- "content-hash": "9629f9cd4034ac27ba3fc0bad9d7d652",
+ "content-hash": "1201c33aa339b1d6362847c6c8ed3d6f",
     "packages": ,
     "packages-dev": [
         {
@@ -407,58 +407,59 @@
         },
         {
             "name": "friendsofphp/php-cs-fixer",
- "version": "v3.75.0",
+ "version": "v3.84.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git&quot;,
- "reference": "399a128ff2fdaf4281e4e79b755693286cdf325c"
+ "reference": "38dad0767bf2a9b516b976852200ae722fe984ca"
             },
             "dist": {
                 "type": "zip",
- "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/399a128ff2fdaf4281e4e79b755693286cdf325c&quot;,
- "reference": "399a128ff2fdaf4281e4e79b755693286cdf325c",
+ "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/38dad0767bf2a9b516b976852200ae722fe984ca&quot;,
+ "reference": "38dad0767bf2a9b516b976852200ae722fe984ca",
                 "shasum": ""
             },
             "require": {
                 "clue/ndjson-react": "^1.0",
                 "composer/semver": "^3.4",
- "composer/xdebug-handler": "^3.0.3",
+ "composer/xdebug-handler": "^3.0.5",
                 "ext-filter": "*",
                 "ext-hash": "*",
                 "ext-json": "*",
                 "ext-tokenizer": "*",
                 "fidry/cpu-core-counter": "^1.2",
                 "php": "^7.4 || ^8.0",
- "react/child-process": "^0.6.5",
+ "react/child-process": "^0.6.6",
                 "react/event-loop": "^1.0",
- "react/promise": "^2.0 || ^3.0",
+ "react/promise": "^2.11 || ^3.0",
                 "react/socket": "^1.0",
                 "react/stream": "^1.0",
- "sebastian/diff": "^4.0 || ^5.1 || ^6.0 || ^7.0",
- "symfony/console": "^5.4 || ^6.4 || ^7.0",
- "symfony/event-dispatcher": "^5.4 || ^6.4 || ^7.0",
- "symfony/filesystem": "^5.4 || ^6.4 || ^7.0",
- "symfony/finder": "^5.4 || ^6.4 || ^7.0",
- "symfony/options-resolver": "^5.4 || ^6.4 || ^7.0",
- "symfony/polyfill-mbstring": "^1.31",
- "symfony/polyfill-php80": "^1.31",
- "symfony/polyfill-php81": "^1.31",
- "symfony/process": "^5.4 || ^6.4 || ^7.2",
- "symfony/stopwatch": "^5.4 || ^6.4 || ^7.0"
+ "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0",
+ "symfony/console": "^5.4.45 || ^6.4.13 || ^7.0",
+ "symfony/event-dispatcher": "^5.4.45 || ^6.4.13 || ^7.0",
+ "symfony/filesystem": "^5.4.45 || ^6.4.13 || ^7.0",
+ "symfony/finder": "^5.4.45 || ^6.4.17 || ^7.0",
+ "symfony/options-resolver": "^5.4.45 || ^6.4.16 || ^7.0",
+ "symfony/polyfill-mbstring": "^1.32",
+ "symfony/polyfill-php80": "^1.32",
+ "symfony/polyfill-php81": "^1.32",
+ "symfony/process": "^5.4.47 || ^6.4.20 || ^7.2",
+ "symfony/stopwatch": "^5.4.45 || ^6.4.19 || ^7.0"
             },
             "require-dev": {
                 "facile-it/paraunit": "^1.3.1 || ^2.6",
                 "infection/infection": "^0.29.14",
- "justinrainbow/json-schema": "^5.3 || ^6.2",
- "keradus/cli-executor": "^2.1",
+ "justinrainbow/json-schema": "^5.3 || ^6.4",
+ "keradus/cli-executor": "^2.2",
                 "mikey179/vfsstream": "^1.6.12",
- "php-coveralls/php-coveralls": "^2.7",
+ "php-coveralls/php-coveralls": "^2.8",
                 "php-cs-fixer/accessible-object": "^1.1",
                 "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6",
                 "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6",
- "phpunit/phpunit": "^9.6.22 || ^10.5.45 || ^11.5.12",
- "symfony/var-dumper": "^5.4.48 || ^6.4.18 || ^7.2.3",
- "symfony/yaml": "^5.4.45 || ^6.4.18 || ^7.2.3"
+ "phpunit/phpunit": "^9.6.23 || ^10.5.47 || ^11.5.25",
+ "symfony/polyfill-php84": "^1.32",
+ "symfony/var-dumper": "^5.4.48 || ^6.4.23 || ^7.3.1",
+ "symfony/yaml": "^5.4.45 || ^6.4.23 || ^7.3.1"
             },
             "suggest": {
                 "ext-dom": "For handling output formats in XML",
@@ -499,7 +500,7 @@
             ],
             "support": {
                 "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues&quot;,
- "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.75.0&quot;
+ "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.84.0&quot;
             },
             "funding": [
                 {
@@ -507,7 +508,7 @@
                     "type": "github"
                 }
             ],
- "time": "2025-03-31T18:40:42+00:00"
+ "time": "2025-07-15T18:21:57+00:00"
         },
         {
             "name": "myclabs/deep-copy",
@@ -2828,23 +2829,24 @@
         },
         {
             "name": "symfony/console",
- "version": "v7.2.5",
+ "version": "v7.3.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/console.git&quot;,
- "reference": "e51498ea18570c062e7df29d05a7003585b19b88"
+ "reference": "9e27aecde8f506ba0fd1d9989620c04a87697101"
             },
             "dist": {
                 "type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/e51498ea18570c062e7df29d05a7003585b19b88&quot;,
- "reference": "e51498ea18570c062e7df29d05a7003585b19b88",
+ "url": "https://api.github.com/repos/symfony/console/zipball/9e27aecde8f506ba0fd1d9989620c04a87697101&quot;,
+ "reference": "9e27aecde8f506ba0fd1d9989620c04a87697101",
                 "shasum": ""
             },
             "require": {
                 "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3",
                 "symfony/polyfill-mbstring": "~1.0",
                 "symfony/service-contracts": "^2.5|^3",
- "symfony/string": "^6.4|^7.0"
+ "symfony/string": "^7.2"
             },
             "conflict": {
                 "symfony/dependency-injection": "<6.4",
@@ -2901,7 +2903,7 @@
                 "terminal"
             ],
             "support": {
- "source": "https://github.com/symfony/console/tree/v7.2.5&quot;
+ "source": "https://github.com/symfony/console/tree/v7.3.1&quot;
             },
             "funding": [
                 {
@@ -2917,20 +2919,20 @@
                     "type": "tidelift"
                 }
             ],
- "time": "2025-03-12T08:11:12+00:00"
+ "time": "2025-06-27T19:55:54+00:00"
         },
         {
             "name": "symfony/deprecation-contracts",
- "version": "v3.5.1",
+ "version": "v3.6.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/deprecation-contracts.git&quot;,
- "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6"
+ "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62"
             },
             "dist": {
                 "type": "zip",
- "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6&quot;,
- "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62&quot;,
+ "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62",
                 "shasum": ""
             },
             "require": {
@@ -2943,7 +2945,7 @@
                     "name": "symfony/contracts"
                 },
                 "branch-alias": {
- "dev-main": "3.5-dev"
+ "dev-main": "3.6-dev"
                 }
             },
             "autoload": {
@@ -2968,7 +2970,7 @@
             "description": "A generic function and convention to trigger deprecation notices",
             "homepage": "https://symfony.com",
             "support": {
- "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1&quot;
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0&quot;
             },
             "funding": [
                 {
@@ -2984,20 +2986,20 @@
                     "type": "tidelift"
                 }
             ],
- "time": "2024-09-25T14:20:29+00:00"
+ "time": "2024-09-25T14:21:43+00:00"
         },
         {
             "name": "symfony/event-dispatcher",
- "version": "v7.2.0",
+ "version": "v7.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/event-dispatcher.git&quot;,
- "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1"
+ "reference": "497f73ac996a598c92409b44ac43b6690c4f666d"
             },
             "dist": {
                 "type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1&quot;,
- "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/497f73ac996a598c92409b44ac43b6690c4f666d&quot;,
+ "reference": "497f73ac996a598c92409b44ac43b6690c4f666d",
                 "shasum": ""
             },
             "require": {
@@ -3048,7 +3050,7 @@
             "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
             "homepage": "https://symfony.com",
             "support": {
- "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0&quot;
+ "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.0&quot;
             },
             "funding": [
                 {
@@ -3064,20 +3066,20 @@
                     "type": "tidelift"
                 }
             ],
- "time": "2024-09-25T14:21:43+00:00"
+ "time": "2025-04-22T09:11:45+00:00"
         },
         {
             "name": "symfony/event-dispatcher-contracts",
- "version": "v3.5.1",
+ "version": "v3.6.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/event-dispatcher-contracts.git&quot;,
- "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f"
+ "reference": "59eb412e93815df44f05f342958efa9f46b1e586"
             },
             "dist": {
                 "type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f&quot;,
- "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586&quot;,
+ "reference": "59eb412e93815df44f05f342958efa9f46b1e586",
                 "shasum": ""
             },
             "require": {
@@ -3091,7 +3093,7 @@
                     "name": "symfony/contracts"
                 },
                 "branch-alias": {
- "dev-main": "3.5-dev"
+ "dev-main": "3.6-dev"
                 }
             },
             "autoload": {
@@ -3124,7 +3126,7 @@
                 "standards"
             ],
             "support": {
- "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1&quot;
+ "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0&quot;
             },
             "funding": [
                 {
@@ -3140,11 +3142,11 @@
                     "type": "tidelift"
                 }
             ],
- "time": "2024-09-25T14:20:29+00:00"
+ "time": "2024-09-25T14:21:43+00:00"
         },
         {
             "name": "symfony/filesystem",
- "version": "v7.2.0",
+ "version": "v7.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/filesystem.git&quot;,
@@ -3190,7 +3192,7 @@
             "description": "Provides basic utilities for the filesystem",
             "homepage": "https://symfony.com",
             "support": {
- "source": "https://github.com/symfony/filesystem/tree/v7.2.0&quot;
+ "source": "https://github.com/symfony/filesystem/tree/v7.3.0&quot;
             },
             "funding": [
                 {
@@ -3210,16 +3212,16 @@
         },
         {
             "name": "symfony/finder",
- "version": "v7.2.2",
+ "version": "v7.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/finder.git&quot;,
- "reference": "87a71856f2f56e4100373e92529eed3171695cfb"
+ "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d"
             },
             "dist": {
                 "type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb&quot;,
- "reference": "87a71856f2f56e4100373e92529eed3171695cfb",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/ec2344cf77a48253bbca6939aa3d2477773ea63d&quot;,
+ "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d",
                 "shasum": ""
             },
             "require": {
@@ -3254,7 +3256,7 @@
             "description": "Finds files and directories via an intuitive fluent interface",
             "homepage": "https://symfony.com",
             "support": {
- "source": "https://github.com/symfony/finder/tree/v7.2.2&quot;
+ "source": "https://github.com/symfony/finder/tree/v7.3.0&quot;
             },
             "funding": [
                 {
@@ -3270,20 +3272,20 @@
                     "type": "tidelift"
                 }
             ],
- "time": "2024-12-30T19:00:17+00:00"
+ "time": "2024-12-30T19:00:26+00:00"
         },
         {
             "name": "symfony/options-resolver",
- "version": "v7.2.0",
+ "version": "v7.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/options-resolver.git&quot;,
- "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50"
+ "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca"
             },
             "dist": {
                 "type": "zip",
- "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50&quot;,
- "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/afb9a8038025e5dbc657378bfab9198d75f10fca&quot;,
+ "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca",
                 "shasum": ""
             },
             "require": {
@@ -3321,7 +3323,7 @@
                 "options"
             ],
             "support": {
- "source": "https://github.com/symfony/options-resolver/tree/v7.2.0&quot;
+ "source": "https://github.com/symfony/options-resolver/tree/v7.3.0&quot;
             },
             "funding": [
                 {
@@ -3337,11 +3339,11 @@
                     "type": "tidelift"
                 }
             ],
- "time": "2024-11-20T11:17:29+00:00"
+ "time": "2025-04-04T13:12:05+00:00"
         },
         {
             "name": "symfony/polyfill-ctype",
- "version": "v1.31.0",
+ "version": "v1.32.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-ctype.git&quot;,
@@ -3400,7 +3402,7 @@
                 "portable"
             ],
             "support": {
- "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0&quot;
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0&quot;
             },
             "funding": [
                 {
@@ -3420,7 +3422,7 @@
         },
         {
             "name": "symfony/polyfill-intl-grapheme",
- "version": "v1.31.0",
+ "version": "v1.32.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-intl-grapheme.git&quot;,
@@ -3478,7 +3480,7 @@
                 "shim"
             ],
             "support": {
- "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0&quot;
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0&quot;
             },
             "funding": [
                 {
@@ -3498,7 +3500,7 @@
         },
         {
             "name": "symfony/polyfill-intl-normalizer",
- "version": "v1.31.0",
+ "version": "v1.32.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-intl-normalizer.git&quot;,
@@ -3559,7 +3561,7 @@
                 "shim"
             ],
             "support": {
- "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0&quot;
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0&quot;
             },
             "funding": [
                 {
@@ -3579,19 +3581,20 @@
         },
         {
             "name": "symfony/polyfill-mbstring",
- "version": "v1.31.0",
+ "version": "v1.32.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-mbstring.git&quot;,
- "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341"
+ "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493"
             },
             "dist": {
                 "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341&quot;,
- "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493&quot;,
+ "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493",
                 "shasum": ""
             },
             "require": {
+ "ext-iconv": "*",
                 "php": ">=7.2"
             },
             "provide": {
@@ -3639,7 +3642,7 @@
                 "shim"
             ],
             "support": {
- "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0&quot;
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0&quot;
             },
             "funding": [
                 {
@@ -3655,20 +3658,20 @@
                     "type": "tidelift"
                 }
             ],
- "time": "2024-09-09T11:45:10+00:00"
+ "time": "2024-12-23T08:48:59+00:00"
         },
         {
             "name": "symfony/polyfill-php80",
- "version": "v1.31.0",
+ "version": "v1.32.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-php80.git&quot;,
- "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8"
+ "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608"
             },
             "dist": {
                 "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8&quot;,
- "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608&quot;,
+ "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
                 "shasum": ""
             },
             "require": {
@@ -3719,7 +3722,7 @@
                 "shim"
             ],
             "support": {
- "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0&quot;
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0&quot;
             },
             "funding": [
                 {
@@ -3735,11 +3738,11 @@
                     "type": "tidelift"
                 }
             ],
- "time": "2024-09-09T11:45:10+00:00"
+ "time": "2025-01-02T08:10:11+00:00"
         },
         {
             "name": "symfony/polyfill-php81",
- "version": "v1.31.0",
+ "version": "v1.32.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-php81.git&quot;,
@@ -3795,7 +3798,7 @@
                 "shim"
             ],
             "support": {
- "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0&quot;
+ "source": "https://github.com/symfony/polyfill-php81/tree/v1.32.0&quot;
             },
             "funding": [
                 {
@@ -3815,16 +3818,16 @@
         },
         {
             "name": "symfony/process",
- "version": "v7.2.5",
+ "version": "v7.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/process.git&quot;,
- "reference": "87b7c93e57df9d8e39a093d32587702380ff045d"
+ "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af"
             },
             "dist": {
                 "type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d&quot;,
- "reference": "87b7c93e57df9d8e39a093d32587702380ff045d",
+ "url": "https://api.github.com/repos/symfony/process/zipball/40c295f2deb408d5e9d2d32b8ba1dd61e36f05af&quot;,
+ "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af",
                 "shasum": ""
             },
             "require": {
@@ -3856,7 +3859,7 @@
             "description": "Executes commands in sub-processes",
             "homepage": "https://symfony.com",
             "support": {
- "source": "https://github.com/symfony/process/tree/v7.2.5&quot;
+ "source": "https://github.com/symfony/process/tree/v7.3.0&quot;
             },
             "funding": [
                 {
@@ -3872,20 +3875,20 @@
                     "type": "tidelift"
                 }
             ],
- "time": "2025-03-13T12:21:46+00:00"
+ "time": "2025-04-17T09:11:12+00:00"
         },
         {
             "name": "symfony/service-contracts",
- "version": "v3.5.1",
+ "version": "v3.6.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/service-contracts.git&quot;,
- "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0"
+ "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4"
             },
             "dist": {
                 "type": "zip",
- "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0&quot;,
- "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4&quot;,
+ "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
                 "shasum": ""
             },
             "require": {
@@ -3903,7 +3906,7 @@
                     "name": "symfony/contracts"
                 },
                 "branch-alias": {
- "dev-main": "3.5-dev"
+ "dev-main": "3.6-dev"
                 }
             },
             "autoload": {
@@ -3939,7 +3942,7 @@
                 "standards"
             ],
             "support": {
- "source": "https://github.com/symfony/service-contracts/tree/v3.5.1&quot;
+ "source": "https://github.com/symfony/service-contracts/tree/v3.6.0&quot;
             },
             "funding": [
                 {
@@ -3955,11 +3958,11 @@
                     "type": "tidelift"
                 }
             ],
- "time": "2024-09-25T14:20:29+00:00"
+ "time": "2025-04-25T09:37:31+00:00"
         },
         {
             "name": "symfony/stopwatch",
- "version": "v7.2.4",
+ "version": "v7.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/stopwatch.git&quot;,
@@ -4001,7 +4004,7 @@
             "description": "Provides a way to profile code",
             "homepage": "https://symfony.com",
             "support": {
- "source": "https://github.com/symfony/stopwatch/tree/v7.2.4&quot;
+ "source": "https://github.com/symfony/stopwatch/tree/v7.3.0&quot;
             },
             "funding": [
                 {
@@ -4021,16 +4024,16 @@
         },
         {
             "name": "symfony/string",
- "version": "v7.2.0",
+ "version": "v7.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/string.git&quot;,
- "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82"
+ "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125"
             },
             "dist": {
                 "type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82&quot;,
- "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82",
+ "url": "https://api.github.com/repos/symfony/string/zipball/f3570b8c61ca887a9e2938e85cb6458515d2b125&quot;,
+ "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125",
                 "shasum": ""
             },
             "require": {
@@ -4088,7 +4091,7 @@
                 "utf8"
             ],
             "support": {
- "source": "https://github.com/symfony/string/tree/v7.2.0&quot;
+ "source": "https://github.com/symfony/string/tree/v7.3.0&quot;
             },
             "funding": [
                 {
@@ -4104,7 +4107,7 @@
                     "type": "tidelift"
                 }
             ],
- "time": "2024-11-13T13:31:26+00:00"
+ "time": "2025-04-20T20:19:01+00:00"
         },
         {
             "name": "theseer/tokenizer",
@@ -4159,7 +4162,7 @@
     ],
     "aliases": ,
     "minimum-stability": "stable",
- "stability-flags": ,
+ "stability-flags": {},
     "prefer-stable": false,
     "prefer-lowest": false,
     "platform": {
@@ -4171,5 +4174,5 @@
     "platform-overrides": {
         "php": "8.2.0"
     },
- "plugin-api-version": "2.3.0"
+ "plugin-api-version": "2.6.0"
}
diff --git a/conferences/index.php b/conferences/index.php
index 4ed6dd0627..3718ba5baf 100644
--- a/conferences/index.php
+++ b/conferences/index.php
@@ -1,8 +1,9 @@
<?php

+use phpweb\News\NewsHandler;
+
$_SERVER['BASE_PAGE'] = 'conferences/index.php';
include_once __DIR__ . '/../include/prepend.inc';
-include_once __DIR__ . '/../include/pregen-news.inc';

mirror_setcookie("LAST_NEWS", $_SERVER["REQUEST_TIME"], 60 * 60 * 24 * 365);
site_header("PHP Conferences around the world", [
@@ -12,22 +13,9 @@
]);

$content = "<div class='home-content'>";
-$frontpage = ;
-foreach ($NEWS_ENTRIES as $entry) {
- foreach ($entry["category"] as $category) {
- if ($category["term"] == "cfp") {
- $frontpage = $entry;
- break;
- }
- if ($category["term"] == "conferences") {
- $frontpage = $entry;
- break;
- }
- }
-}
$panels = '<p class="prepend"><a href="https://wiki.php.net/conferences&quot;&gt;Want to see your conference appear here?</a></p>';

-foreach ($frontpage as $entry) {
+foreach ((new NewsHandler())->getConferences() as $entry) {
     $link = preg_replace('~^(http://php.net/|https://www.php.net/)~', '', $entry["id"]);
     $id = parse_url($entry["id"], PHP_URL_FRAGMENT);
     $date = date_format(date_create($entry["updated"]), 'Y-m-d');
diff --git a/copyright.php b/copyright.php
index d942c4f9c1..57233ded2c 100644
--- a/copyright.php
+++ b/copyright.php
@@ -1,14 +1,6 @@
<?php
$_SERVER['BASE_PAGE'] = 'copyright.php';
include_once __DIR__ . '/include/prepend.inc';
-$SIDEBAR_DATA = '
-<a id="license"></a>
-<h3>PHP License</h3>
-<p>
- For information on the PHP License (i.e. using the PHP language),
- <a href="/license/">see our licensing information page</a>.
-</p>
-';
site_header("Copyright", ["current" => "footer"]);
?>

diff --git a/distributions b/distributions
index 267ce3a109..44ff5ec604 160000
--- a/distributions
+++ b/distributions
@@ -1 +1 @@
-Subproject commit 267ce3a109f04ee1e68b9b18fa5557c3d9f16958
+Subproject commit 44ff5ec6043005f51463389b1066f22e33a605d7
diff --git a/elephpant.php b/elephpant.php
index 6b8aca09cf..cab6dcf0c4 100644
--- a/elephpant.php
+++ b/elephpant.php
@@ -1,14 +1,6 @@
<?php
$_SERVER['BASE_PAGE'] = 'elephpant.php';
include_once __DIR__ . '/include/prepend.inc';
-$SIDEBAR_DATA = '
-<a id="license"></a>
-<h3>PHP License</h3>
-<p>
- For information on the PHP License (i.e. using the PHP language),
- <a href="/license/">see our licensing information page</a>.
-</p>
-';
site_header("ElePHPant", ["current" => "footer"]);
?>

diff --git a/git.php b/git.php
index 429974fce7..03e1d999c2 100644
--- a/git.php
+++ b/git.php
@@ -99,20 +99,20 @@
  <li>
   You can then check out the branch you want to build, for example:
   <br><br>
- <strong>PHP 7.4</strong>:
- <code>git checkout PHP-7.4</code>
+ <strong>PHP HEAD</strong>:
+ <code>git checkout master</code>
   <br>
- <strong>PHP 8.0</strong>:
- <code>git checkout PHP-8.0</code>
+ <strong>PHP 8.4</strong>:
+ <code>git checkout PHP-8.4</code>
   <br>
- <strong>PHP 8.1</strong>:
- <code>git checkout PHP-8.1</code>
+ <strong>PHP 8.3</strong>:
+ <code>git checkout PHP-8.3</code>
   <br>
   <strong>PHP 8.2</strong>:
   <code>git checkout PHP-8.2</code>
   <br>
- <strong>PHP HEAD</strong>:
- <code>git checkout master</code>
+ <strong>PHP 8.1</strong>:
+ <code>git checkout PHP-8.1</code>
   <br><br>
  </li>

diff --git a/include/branches.inc b/include/branches.inc
index f3795963f7..deb1f79841 100644
--- a/include/branches.inc
+++ b/include/branches.inc
@@ -355,7 +355,7 @@ function get_branch_release_date($branch): ?DateTime
{
     $initial = get_initial_release($branch);

- return $initial ? new DateTime($initial['date']) : null;
+ return isset($initial['date']) ? new DateTime($initial['date']) : null;
}

function get_branch_support_state($branch) {
diff --git a/include/gpg-keys.inc b/include/gpg-keys.inc
index b3aaeae389..861981e44b 100644
--- a/include/gpg-keys.inc
+++ b/include/gpg-keys.inc
@@ -47,6 +47,12 @@ function gpg_key_get(string $rm): ?string {
                 " Key fingerprint = CBAF 69F1 73A0 FEA4 B537 F470 D66C 9593 118B CCB6\n" .
                 "uid Christoph M. Becker <cmb@php.net>";

+ case 'daniels':
+ return
+ "pub rsa4096 2025-06-08 [SCEA]\n" .
+ " D95C 03BC 702B E951 5344 AE33 74E4 4BC9 0677 01A5\n" .
+ "uid [ultimate] Daniel Scherzer (for PHP) <daniels@php.net>";
+
         case 'davey':
             return
                 "pub 4096R/7BD5DCD0 2016-05-07\n" .
@@ -69,6 +75,13 @@ function gpg_key_get(string $rm): ?string {
                 " Key fingerprint = 0B96 609E 270F 565C 1329 2B24 C13C 70B8 7267 B52D\n" .
                 "uid David Soria Parra <dsp@php.net>";

+ case 'edorian':
+ return
+ "pub ed25519 2025-06-08 [SC]\n" .
+ " 49D9 AF6B C72A 80D6 6917 19C8 AA23 F5BE 9C70 97D4\n" .
+ "uid [ultimate] Volker Dusch <edorian@php.net>\n" .
+ "sub cv25519 2025-06-08 [E]";
+
         case 'ericmann':
             return
                 "pub rsa4096 2016-11-25 [SC]\n" .
@@ -177,6 +190,7 @@ function gpg_key_get(string $rm): ?string {

function gpg_key_get_branches(bool $activeOnly): array {
     $branches = [
+ '8.5' => ['pierrick', 'edorian', 'daniels'],
         '8.4' => ['ericmann', 'calvinb', 'saki'],
         '8.3' => ['pierrick', 'ericmann', 'bukka'],
         '8.2' => ['pierrick', 'ramsey', 'sergey'],
diff --git a/include/header.inc b/include/header.inc
index f6667a4e30..b4160dd3f2 100644
--- a/include/header.inc
+++ b/include/header.inc
@@ -61,15 +61,23 @@ if (!isset($config["languages"])) {
   <meta charset="utf-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">

+ <?php if (!empty($_SERVER["BASE_HREF"])): ?>
+ <base href="<?php echo $_SERVER["BASE_HREF"]; ?>">
+ <?php endif ?>
+
   <title>PHP: <?php echo $title ?></title>

+ <?php foreach($CSS as $filename => $modified): ?>
+ <link rel="stylesheet" type="text/css" href="/cached.php?t=<?php echo $modified?>&amp;f=<?php echo $filename?>" media="screen">
+ <?php endforeach ?>
+
  <link rel="icon" type="image/svg+xml" sizes="any" href="<?php echo $MYSITE ?>favicon.svg?v=2">
  <link rel="icon" type="image/png" sizes="196x196" href="<?php echo $MYSITE ?>favicon-196x196.png?v=2">
  <link rel="icon" type="image/png" sizes="32x32" href="<?php echo $MYSITE ?>favicon-32x32.png?v=2">
  <link rel="icon" type="image/png" sizes="16x16" href="<?php echo $MYSITE ?>favicon-16x16.png?v=2">
  <link rel="shortcut icon" href="<?php echo $MYSITE ?>favicon.ico?v=2">

- <link rel="search" type="application/opensearchdescription+xml" href="http://php.net/phpnetimprovedsearch.src&quot; title="Add PHP.net search">
+ <link rel="search" type="application/opensearchdescription+xml" href="https://www.php.net/phpnetimprovedsearch.src&quot; title="Add PHP.net search">
  <link rel="alternate" type="application/atom+xml" href="<?php echo $MYSITE ?>releases/feed.php" title="PHP Release feed">
  <link rel="alternate" type="application/atom+xml" href="<?php echo $MYSITE ?>feed.atom" title="PHP: Hypertext Preprocessor">

@@ -89,18 +97,6 @@ if (!isset($config["languages"])) {
  <link rel="alternate" href="<?php echo $MYSITE ?>manual/<?php echo $code?>/<?php echo $config["thispage"] ?>" hreflang="<?php echo $code?>">
<?php endforeach ?>

-<?php foreach($CSS as $filename => $modified): ?>
-<link rel="stylesheet" type="text/css" href="/cached.php?t=<?php echo $modified?>&amp;f=<?php echo $filename?>" media="screen">
-<?php endforeach ?>
-
-<?php foreach($JS as $filename => $modified): ?>
-<script type="text/javascript" src="/cached.php?t=<?php echo $modified?>&amp;f=<?php echo $filename?>"></script>
-<?php endforeach ?>
-
-<?php if (!empty($_SERVER["BASE_HREF"])): ?>
- <base href="<?php echo $_SERVER["BASE_HREF"] ?>">
-<?php endif ?>
-
<?php if (isset($config['meta_tags'])) { echo $config['meta_tags']; } ?>

<?php if (is_primary_site()) { ?>
diff --git a/include/layout.inc b/include/layout.inc
index b3dc6dbfa9..c69d390b32 100644
--- a/include/layout.inc
+++ b/include/layout.inc
@@ -2,6 +2,7 @@

use phpweb\I18n\Languages;
use phpweb\Navigation\NavItem;
+use phpweb\News\NewsHandler;

$_SERVER['STATIC_ROOT'] = $MYSITE;
$_SERVER['MYSITE'] = $MYSITE;
@@ -346,7 +347,7 @@ function news_archive_sidebar(): void
}

// Print news
-function print_news($news, $dog, $max = 5, $onlyyear = null, $return = false) {
+function print_news($news, $dog, $max = 5, $return = false) {
     $retval = ;
     $count = 0;
     $news = $news ?: ; // default to empty array (if no news)
@@ -391,10 +392,6 @@ function print_news($news, $dog, $max = 5, $onlyyear = null, $return = false) {
         $published = substr($item["published"], 0, 10);
         $nixtimestamp = strtotime($published);
         $newsdate = date("d M Y", $nixtimestamp);
- if ($onlyyear && date("Y", $nixtimestamp) != $onlyyear) {
- $count--;
- continue;
- }

         if ($return) {
             $retval = [
@@ -518,8 +515,12 @@ function get_nav_items(): array {

function get_news_changes()
{
- include __DIR__ . "/pregen-news.inc";
- $date = date_create($NEWS_ENTRIES[0]["updated"]);
+ $lastNews = (new NewsHandler())->getLastestNews();
+ if ($lastNews === null) {
+ return false;
+ }
+
+ $date = date_create($lastNews["updated"]);
     if (isset($_COOKIE["LAST_NEWS"]) && $_COOKIE["LAST_NEWS"] >= $date->getTimestamp()) {
         return false;
     }
@@ -534,8 +535,8 @@ function get_news_changes()

     $date->modify("+1 week");
     if ($date->getTimestamp() > $_SERVER["REQUEST_TIME"]) {
- $link = preg_replace('~^(http://php.net/|https://www.php.net/)~‘, '/', $NEWS_ENTRIES[0]["link"][0]["href"]);
- $title = $NEWS_ENTRIES[0]["title"];
+ $link = preg_replace('~^(http://php.net/|https://www.php.net/)~’, '/', $lastNews["link"][0]["href"]);
+ $title = $lastNews["title"];
         return "<a href='{$link}'>{$title}</a>";
     }
     return false;
diff --git a/include/release-qa.php b/include/release-qa.php
index 3a1098313e..45e2ad2eae 100644
--- a/include/release-qa.php
+++ b/include/release-qa.php
@@ -71,29 +71,42 @@
         ],
     ],

- '8.3.22' => [
+ '8.3.24' => [
         'active' => true,
         'release' => [
             'type' => 'RC',
- 'number' => 0,
- 'sha256_bz2' => '',
- 'sha256_gz' => '',
- 'sha256_xz' => '',
- 'date' => '22 May 2025',
- 'baseurl' => 'https://downloads.php.net/‘,
+ 'number' => 1,
+ 'sha256_bz2' => '4b0952b0e6e40aa29bfc166382b963b1d23d5ae7fd9891a8f84bdb6269dd4750',
+ 'sha256_gz' => '76599db84ad4034f0b318405a59170c61e463eecfdde0aeb9c6fd00a14360d06',
+ 'sha256_xz' => '58ac41b231d3d0c7e44f2f6826511c3bed0a09490da4708dac80c7cefc020533',
+ 'date' => '17 Jul 2025',
+ 'baseurl' => 'https://downloads.php.net/~jakub/’,
         ],
     ],

- '8.4.8' => [
+ '8.4.11' => [
         'active' => true,
         'release' => [
             'type' => 'RC',
- 'number' => 0,
- 'sha256_bz2' => '',
- 'sha256_gz' => '',
- 'sha256_xz' => '',
- 'date' => '22 May 2025',
- 'baseurl' => 'https://downloads.php.net/‘,
+ 'number' => 1,
+ 'sha256_bz2' => '641fcd2da3c066a0799cf469ee8491d98502cf5877be5cf07b3d648ac74f83f8',
+ 'sha256_gz' => 'c19c5daa94c8171c5ceb04214212cc7cc5c284804de0f60e2a78d3aec5e65900',
+ 'sha256_xz' => '7568a75d1f220fe224dc56b17f9252bdc366ad9afcc35d8785d58cd1222f6e1f',
+ 'date' => '17 Jul 2025',
+ 'baseurl' => 'https://downloads.php.net/~calvinb/’,
+ ],
+ ],
+
+ '8.5.0' => [
+ 'active' => true,
+ 'release' => [
+ 'type' => 'alpha',
+ 'number' => 2,
+ 'sha256_bz2' => '3394e354cb8f7757bba10d666504d7b1b6e74fd2ed623cd6a1580408c85e5fcb',
+ 'sha256_gz' => '60868a9cb73726c247226b048bfa3727a4a6a72ced283e5351e16d84abf9398e',
+ 'sha256_xz' => '94d41a8168988e5faa744780ad870ee50dd5175b474477cb701fddddf1a696a1',
+ 'date' => '17 Jul 2025',
+ 'baseurl' => 'https://downloads.php.net/~edorian/',
         ],
     ],
];
diff --git a/include/releases.inc b/include/releases.inc
index 5efaf01488..246b21e7a2 100644
--- a/include/releases.inc
+++ b/include/releases.inc
@@ -2,6 +2,152 @@
$OLDRELEASES = array (
   8 =>
   array (
+ '8.3.22' =>
+ array (
+ 'announcement' =>
+ array (
+ 'English' => '/releases/8_3_22.php',
+ ),
+ 'tags' =>
+ array (
+ ),
+ 'date' => '5 Jun 2025',
+ 'source' =>
+ array (
+ 0 =>
+ array (
+ 'filename' => 'php-8.3.22.tar.gz',
+ 'name' => 'PHP 8.3.22 (tar.gz)',
+ 'sha256' => '8fc57c9df455354679e4a127defb60e1af8718ece4cd4827e500f5c7f2449103',
+ 'date' => '5 Jun 2025',
+ ),
+ 1 =>
+ array (
+ 'filename' => 'php-8.3.22.tar.bz2',
+ 'name' => 'PHP 8.3.22 (tar.bz2)',
+ 'sha256' => '99133e2cda2af37baa79db17d8efd414628f14a02ec75f1418a0aa3f6aa6673b',
+ 'date' => '5 Jun 2025',
+ ),
+ 2 =>
+ array (
+ 'filename' => 'php-8.3.22.tar.xz',
+ 'name' => 'PHP 8.3.22 (tar.xz)',
+ 'sha256' => '66c86889059bd27ccf460590ca48fcaf3261349cc9bdba2023ac6a265beabf36',
+ 'date' => '5 Jun 2025',
+ ),
+ ),
+ 'museum' => false,
+ ),
+ '8.1.32' =>
+ array (
+ 'announcement' =>
+ array (
+ 'English' => '/releases/8_1_32.php',
+ ),
+ 'tags' =>
+ array (
+ 0 => 'security',
+ ),
+ 'date' => '13 Mar 2025',
+ 'source' =>
+ array (
+ 0 =>
+ array (
+ 'filename' => 'php-8.1.32.tar.gz',
+ 'name' => 'PHP 8.1.32 (tar.gz)',
+ 'sha256' => '4846836d1de27dbd28e89180f073531087029a77e98e8e019b7b2eddbdb1baff',
+ 'date' => '13 Mar 2025',
+ ),
+ 1 =>
+ array (
+ 'filename' => 'php-8.1.32.tar.bz2',
+ 'name' => 'PHP 8.1.32 (tar.bz2)',
+ 'sha256' => 'a04fdd3df05f948df8a8f2c5d27ab54c1f43822c525f31fd20c19a282452d07c',
+ 'date' => '13 Mar 2025',
+ ),
+ 2 =>
+ array (
+ 'filename' => 'php-8.1.32.tar.xz',
+ 'name' => 'PHP 8.1.32 (tar.xz)',
+ 'sha256' => 'c582ac682a280bbc69bc2186c21eb7e3313cc73099be61a6bc1d2cd337cbf383',
+ 'date' => '13 Mar 2025',
+ ),
+ ),
+ 'museum' => false,
+ ),
+ '8.2.28' =>
+ array (
+ 'announcement' =>
+ array (
+ 'English' => '/releases/8_2_28.php',
+ ),
+ 'tags' =>
+ array (
+ 0 => 'security',
+ ),
+ 'date' => '13 Mar 2025',
+ 'source' =>
+ array (
+ 0 =>
+ array (
+ 'filename' => 'php-8.2.28.tar.gz',
+ 'name' => 'PHP 8.2.28 (tar.gz)',
+ 'sha256' => '3318300888de5023720cc84efad5e005e53f30b5f0072fae65a750dabcaf6ec3',
+ 'date' => '13 Mar 2025',
+ ),
+ 1 =>
+ array (
+ 'filename' => 'php-8.2.28.tar.bz2',
+ 'name' => 'PHP 8.2.28 (tar.bz2)',
+ 'sha256' => '2919cc1b92190a58dc17904b92e626600b96ce49a4c72e77513786a4406acce5',
+ 'date' => '13 Mar 2025',
+ ),
+ 2 =>
+ array (
+ 'filename' => 'php-8.2.28.tar.xz',
+ 'name' => 'PHP 8.2.28 (tar.xz)',
+ 'sha256' => 'af8c9153153a7f489153b7a74f2f29a5ee36f5cb2c6c6929c98411a577e89c91',
+ 'date' => '13 Mar 2025',
+ ),
+ ),
+ 'museum' => false,
+ ),
+ '8.4.8' =>
+ array (
+ 'announcement' =>
+ array (
+ 'English' => '/releases/8_4_8.php',
+ ),
+ 'tags' =>
+ array (
+ ),
+ 'date' => '5 Jun 2025',
+ 'source' =>
+ array (
+ 0 =>
+ array (
+ 'filename' => 'php-8.4.8.tar.gz',
+ 'name' => 'PHP 8.4.8 (tar.gz)',
+ 'sha256' => '26d5ae014925b7dee3a61ec02422795f008fbb3a36f9355edaee2d9d78b89b07',
+ 'date' => '5 Jun 2025',
+ ),
+ 1 =>
+ array (
+ 'filename' => 'php-8.4.8.tar.bz2',
+ 'name' => 'PHP 8.4.8 (tar.bz2)',
+ 'sha256' => '36569c64dd1499e570c436603b641eee7cde4af576af786597d0ee711b3a3a8a',
+ 'date' => '5 Jun 2025',
+ ),
+ 2 =>
+ array (
+ 'filename' => 'php-8.4.8.tar.xz',
+ 'name' => 'PHP 8.4.8 (tar.xz)',
+ 'sha256' => 'aa6a4d330b47eacd83e351658ba8c47747a1e4356456219cfb6d75e7838da091',
+ 'date' => '5 Jun 2025',
+ ),
+ ),
+ 'museum' => false,
+ ),
     '8.3.21' =>
     array (
       'announcement' =>
diff --git a/include/version.inc b/include/version.inc
index 4ba37501a5..d5a400626e 100644
--- a/include/version.inc
+++ b/include/version.inc
@@ -20,49 +20,49 @@ $RELEASES = (function () {

     /* PHP 8.4 Release */
     $data['8.4'] = [
- 'version' => '8.4.8',
- 'date' => '5 Jun 2025',
- 'tags' => , // Set to ['security'] for security releases.
+ 'version' => '8.4.10',
+ 'date' => '3 Jul 2025',
+ 'tags' => ['security'], // Set to ['security'] for security releases.
         'sha256' => [
- 'tar.gz' => '26d5ae014925b7dee3a61ec02422795f008fbb3a36f9355edaee2d9d78b89b07',
- 'tar.bz2' => '36569c64dd1499e570c436603b641eee7cde4af576af786597d0ee711b3a3a8a',
- 'tar.xz' => 'aa6a4d330b47eacd83e351658ba8c47747a1e4356456219cfb6d75e7838da091',
+ 'tar.gz' => 'bd25c40ece60d1b3c879c11f517d335b8d6a872174c32ebb088b9494d8bb2cf2',
+ 'tar.bz2' => '8815d10659cde5f03be4d169205d62b7b29ed0edc7cdd84b6384cda0310c3108',
+ 'tar.xz' => '14983a9ef8800e6bc2d920739fd386054402f7976ca9cd7f711509496f0d2632',
         ]
     ];

     /* PHP 8.3 Release */
     $data['8.3'] = [
- 'version' => '8.3.22',
- 'date' => '5 Jun 2025',
- 'tags' => , // Set to ['security'] for security releases.
+ 'version' => '8.3.23',
+ 'date' => '3 Jul 2025',
+ 'tags' => ['security'], // Set to ['security'] for security releases.
         'sha256' => [
- 'tar.gz' => '8fc57c9df455354679e4a127defb60e1af8718ece4cd4827e500f5c7f2449103',
- 'tar.bz2' => '99133e2cda2af37baa79db17d8efd414628f14a02ec75f1418a0aa3f6aa6673b',
- 'tar.xz' => '66c86889059bd27ccf460590ca48fcaf3261349cc9bdba2023ac6a265beabf36',
+ 'tar.gz' => 'ac9f3d6e9bcf1d5c4d66d2d954f89852c17fd4c5eba5811a3a8db08f38c908c7',
+ 'tar.bz2' => '05488f7b967d90a50932f0674dc356e1b795f522f0298b5ce24b680de233c2d4',
+ 'tar.xz' => '08be64700f703bca6ff1284bf1fdaffa37ae1b9734b6559f8350248e8960a6db',
         ]
     ];

     /* PHP 8.2 Release */
     $data['8.2'] = [
- 'version' => '8.2.28',
- 'date' => '13 Mar 2025',
+ 'version' => '8.2.29',
+ 'date' => '3 Jul 2025',
         'tags' => ['security'], // Set to ['security'] for security releases.
         'sha256' => [
- 'tar.gz' => '3318300888de5023720cc84efad5e005e53f30b5f0072fae65a750dabcaf6ec3',
- 'tar.bz2' => '2919cc1b92190a58dc17904b92e626600b96ce49a4c72e77513786a4406acce5',
- 'tar.xz' => 'af8c9153153a7f489153b7a74f2f29a5ee36f5cb2c6c6929c98411a577e89c91',
+ 'tar.gz' => '0b27d330769d4bc67b1d8864347c38744b289664a946919c3ddb2235d326b3cd',
+ 'tar.bz2' => '51979e8d198cbade2aad4ffe9f53dd3f04f9602d3089e5979985e058ade4267c',
+ 'tar.xz' => '475f991afd2d5b901fb410be407d929bc00c46285d3f439a02c59e8b6fe3589c',
         ]
     ];

     /* PHP 8.1 Release */
     $data['8.1'] = [
- 'version' => '8.1.32',
- 'date' => '13 Mar 2025',
+ 'version' => '8.1.33',
+ 'date' => '3 Jul 2025',
         'tags' => ['security'], // Set to ['security'] for security releases.
         'sha256' => [
- 'tar.gz' => '4846836d1de27dbd28e89180f073531087029a77e98e8e019b7b2eddbdb1baff',
- 'tar.bz2' => 'a04fdd3df05f948df8a8f2c5d27ab54c1f43822c525f31fd20c19a282452d07c',
- 'tar.xz' => 'c582ac682a280bbc69bc2186c21eb7e3313cc73099be61a6bc1d2cd337cbf383',
+ 'tar.gz' => 'ee33568a0e2be0b722b3f9a88cecc578316b66b25c90cd0a4f3b1a5cdc3cd826',
+ 'tar.bz2' => 'b6553451841c1a569865d7fdc83024621ee4434cd8fbfeb0a31588ac9c70685f',
+ 'tar.xz' => '9db83bf4590375562bc1a10b353cccbcf9fcfc56c58b7c8fb814e6865bb928d1',
         ]
     ];

diff --git a/index.php b/index.php
index 42c293ae5b..5e52b8a57c 100644
--- a/index.php
+++ b/index.php
@@ -1,5 +1,7 @@
<?php

+use phpweb\News\NewsHandler;
+
(function ($uri): void {
     // Special redirect cases not able to be captured in error.php
     $shortcuts = [
@@ -51,24 +53,12 @@
include_once 'include/prepend.inc';
include_once 'include/branches.inc';
include_once 'include/pregen-confs.inc';
-include_once 'include/pregen-news.inc';
include_once 'include/version.inc';

mirror_setcookie("LAST_NEWS", $_SERVER["REQUEST_TIME"], 60 * 60 * 24 * 365);

$content = "<div class='home-content'>";
-$frontpage = ;
-foreach ($NEWS_ENTRIES as $entry) {
- foreach ($entry["category"] as $category) {
- if ($category["term"] == "frontpage") {
- $frontpage = $entry;
- if (count($frontpage) >= 25) {
- break 2;
- }
- }
- }
-}
-foreach ($frontpage as $entry) {
+foreach ((new NewsHandler())->getFrontPageNews() as $entry) {
     $link = preg_replace('~^(http://php.net/|https://www.php.net/)~‘, '', $entry["id"]);
     $id = parse_url($entry["id"], PHP_URL_FRAGMENT);
     $date = date_create($entry['updated']);
diff --git a/js/common.js b/js/common.js
index a70f81236f..ee5f190c60 100644
--- a/js/common.js
+++ b/js/common.js
@@ -426,6 +426,7 @@ $(document).ready(function () {
                             link.attr('href', photo.url);
                             link.attr('title', photo.title);
                             image = $('<img>');
+ image.attr('alt', '');
                             image.attr('src', 'data:image/jpeg;base64,' + photo.data);
                             $(node).append(link.append(image));
                         }
diff --git a/license/ZendGrant/PHPAssociation.pdf b/license/ZendGrant/PHPAssociation.pdf
new file mode 100755
index 0000000000..4cd86ff673
Binary files /dev/null and b/license/ZendGrant/PHPAssociation.pdf differ
diff --git a/license/ZendGrant/index.html b/license/ZendGrant/index.html
index 0253b2329a..f4ac5498d0 100644
--- a/license/ZendGrant/index.html
+++ b/license/ZendGrant/index.html
@@ -1,43 +1,10 @@
-<html>
-<head>
-<title>Zend Grant</title>
-</head>
-<body>
-
-<h1>Zend Grant</h1>
-
-<ul>
- <li><a href="ZendGrant.pdf">PDF</a></li>
-</ul>
-
-<p>Links to individual scans as PNG images follow.</p>
-
-<h2>Letter of Grant</h2>
-
-<ul>
- <li><a href="ZendGrant1.png">Page 1</a></li>
- <li><a href="ZendGrant2.png">Page 2</a></li>
-</ul>
-
-<h2>Exhibit 1: Zend Open Source License</h2>
-
-<ul>
- <li><a href="ZendGrant3.png">Page 1</a></li>
- <li><a href="ZendGrant4.png">Page 2</a></li>
-</ul>
-
-<h2>Exhibit 2: Open Source Definition</h2>
-
-<ul>
- <li><a href="ZendGrant5.png">Page 1</a></li>
-</ul>
-
-<h2>Exhibit 3: PHP Open Source License</h2>
-
-<ul>
- <li><a href="ZendGrant6.png">Page 1</a></li>
- <li><a href="ZendGrant7.png">Page 2</a></li>
-</ul>
-
-</body>
+<html lang="en">
+ <head>
+ <meta http-equiv="Refresh" content="15; url='/license/ZendGrant/'">
+ <title>Zend Grant</title>
+ </head>
+ <body>
+ <h1>This page has moved</h1>
+ <p>If you are not redirected within 15 seconds, please <a href="/license/ZendGrant/">click here</a>.</p>
+ </body>
</html>
diff --git a/license/ZendGrant/index.php b/license/ZendGrant/index.php
new file mode 100644
index 0000000000..ed38e8468e
--- /dev/null
+++ b/license/ZendGrant/index.php
@@ -0,0 +1,158 @@
+<?php
+$_SERVER['BASE_PAGE'] = 'license/ZendGrant/index.php';
+include_once __DIR__ . '/../../include/prepend.inc';
+
+$SIDEBAR_DATA = <<<EOF
+<aside>
+ <h3>Exhibit 1</h3>
+
+ <ul>
+ <li><a href="/license/ZendGrant/ZendGrant3.png">Page 1</a></li>
+ <li><a href="/license/ZendGrant/ZendGrant4.png">Page 2</a></li>
+ </ul>
+
+ <h3>Exhibit 2</h3>
+
+ <ul>
+ <li><a href="/license/ZendGrant/ZendGrant5.png">Page 1</a></li>
+ </ul>
+
+ <h3>Exhibit 3</h3>
+
+ <ul>
+ <li><a href="/license/ZendGrant/ZendGrant6.png">Page 1</a></li>
+ <li><a href="/license/ZendGrant/ZendGrant7.png">Page 2</a></li>
+ </ul>
+
+ <h3>Resources</h3>
+
+ <ul>
+ <li><a href="/license/ZendGrant/ZendGrant.pdf">Zend Grant (PDF)</a></li>
+ <li><a href="/license/ZendGrant/PHPAssociation.pdf">PHP Association Articles (PDF)</a></li>
+ </ul>
+</aside>
+EOF;
+
+site_header("Zend Grant", ["current" => "help"]);
+?>
+
+<h1>Zend Grant</h1>
+
+<p>
+ Zend Technologies, Ltd.<br>
+ Jabotinski 35, Ramat Gan<br>
+ Israel
+</p>
+
+<p>May 22, 2000</p>
+
+<p>
+ PHP Association<br>
+ Nebraska
+</p>
+
+<p>Re: <u>Zend Engine</u></p>
+
+<p>
+ As you know, Zend Technologies, Ltd. ("Zend") remains deeply committed to the advancement and
+ proliferation of PHP as an open source web scripting language. Zend currently makes its Zend Engine
+ software available, as a standalone product, under the open-source agreement that may be found at
+ http://www.zend.com/license/ZendLicense.txt (the "Zend Open Source License", a copy of which is
+ attached as Exhibit 1). Since Zend Engine is a crucial component of PHP, Zend hereby makes the following
+ commitments and assurances to The PHP Association (the "Association"):
+</p>
+
+<ul>
+ <li>
+ <p>
+ Zend will continue to make Zend Engine available as an open source product under the Zend
+ Open Source License. If Zend changes the terms of the Zend Open Source License, the new
+ license will be consistent with the Open Source Definition of the Open Source Initiative (see
+ http://www.opensource.org/osd.html, a copy of which is attached as Exhibit 2).
+ </p>
+ </li>
+ <li>
+ <p>
+ Without limitation of the license to Zend Engine granted to all users under the Zend Open
+ Source License, the PHP Association is hereby authorized to market, distribute and sublicense
+ Zend Engine, in source and object code forms, as an integrated component of PHP, to end users
+ who agree to be bound by the PHP open-source license, version 2.02, in the form attached
+ hereto as Exhibit 3 (the "PHP Open Source License"). However, if Zend Engine is either
+ modified or separated from the rest of PHP, the use of the modified or separated Zend Engine
+ shall not be governed by the PHP Open Source License, but instead shall be governed by the
+ Zend Open Source License.
+ </p>
+ </li>
+</ul>
+
+<p>The following additional terms shall apply:</p>
+
+<p>
+ 1. <u>Ownership</u>. As between Zend and the Association, Zend shall retain all rights, title and interest in
+ and to the Zend Engine, including but not limited to, all patents, copyrights, trade secret rights, and any
+ other intellectual property rights inherent therein or appurtenant thereto. The Association will not delete or
+ alter any intellectual property rights or license notices appearing on the Zend Engine and will reproduce and
+ display such notices on each copy it makes of the Zend Engine. The Association's rights in and to the Zend
+ Engine are limited to those expressly granted in this Letter. All other rights are reserved by Zend.
+</p>
+
+<p>
+ 2. <u>Trademarks</u>. The Association may display Zend's trademarks and trade names in connection with
+ the marketing and distribution of PHP (as integrated with the Zend Engine), subject to Zend's then-current
+ trademark policies. Without limitation of the foregoing, the advertisement or other marketing material used
+ by the Association shall not misrepresent any of the technical features or capabilities of the Zend Engine.
+</p>
+
+<p>
+ 3. <u>DISCLAIMER OF WARRANTY</u>. THE ASSOCIATION ACKNOWLEDGES THAT THE ZEND ENGINE IS BEING LICENSED HEREUNDER ON
+ AN "AS-IS" BASIS WITH NO WARRANTY WHATSOEVER. THE ASSOCIATION ACKNOWLEDGES THAT ITS USE AND DISTRIBUTION OF THE ZEND
+ ENGINE AND THE INTEGRATED PRODUCT IS AT ITS OWN RISK. ZEND AND ITS LICENSORS MAKE, AND THE ASSOCIATION RECEIVES, NO
+ WARRANTIES, EXPRESS, IMPLIED, OR OTHERWISE. ZEND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT: ZEND DOES NOT WARRANT THAT THE OPERATION OF THE ZEND ENGINE
+ OR THE INTEGRATED PRODUCT SHALL BE OPERABLE, UNINTERRUPTED OR ERROR FREE OR THAT IT WILL FUNCTION OR OPERATE IN
+ CONJUNCTION WITH ANY OTHER PRODUCT, INCLUDING, WITHOUT LIMITATION, PHP OR ANY VERSION THEREOF.
+</p>
+
+<p>
+ 4. <u>LIMITATIONS OF LIABILITY</u>. IN NO EVENT WILL ZEND BE LIABLE TO THE ASSOCIATION, END USERS OF PHP OR ANY
+ OTHER PARTY FOR ANY SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO THIS LETTER, WHETHER
+ BASED ON BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE), PRODUCT LIABILITY, OR OTHERWISE, AND WHETHER OR NOT ZEND
+ HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. WITHOUT LIMITATION OF THE FOREGOING, UNDER NO CIRCUMSTANCES
+ SHALL ZEND'S TOTAL AGGREGATE LIABILITY UNDER THIS LETTER TO ALL PARTIES, IN THE AGGREGATE, EXCEED ONE HUNDRED
+ DOLLARS ($100). The parties have agreed that the limitations specified in this Section will survive and apply even
+ if any limited remedy specified in this Letter is found to have failed of its essential purpose.
+</p>
+
+<p>
+ 5. <u>GENERAL</u>. The Association may not assign this Letter, by operation of law or otherwise in whole
+ or in part, without Zend's written consent. Any attempt to assign this Letter without such consent will be
+ null and void. This Letter will bind and inure to the benefit of each party's permitted successors and assigns.
+ This Letter will be governed by and construed in accordance with the laws of the State of New York. Any
+ suit hereunder will be brought solely in the federal or state courts in New York State, New York County and
+ both parties hereby submit to the personal jurisdiction thereof. If any provision of this Letter is found
+ invalid or unenforceable, that provision will be enforced to the maximum extent permissible, and the other
+ provisions of this Letter will remain in force. All notices under this Letter will be deemed given when
+ delivered personally, sent by confirmed facsimile transmission, or sent by certified or registered U.S. mail or
+ nationally-recognized express courier, return receipt requested, to the address shown above or as may
+ otherwise be specified by either party to the other in accordance with this section. The parties to this Letter
+ are independent contractors. There is no relationship of partnership, joint venture, employment, franchise,
+ or agency between the parties. Neither party will have the power to bind the other or incur obligations on
+ the other's behalf without the other's prior written consent. No failure of either party to exercise or enforce
+ any of its rights under this Letter will act as a waiver of such rights. This Letter and its attachment are the
+ complete and exclusive agreement between the parties with respect to the subject matter hereof, superseding
+ and replacing any and all prior agreements, communications, and understandings (both written and oral)
+ regarding such subject matter. This Letter may only be modified, or any rights under it waived, by a written
+ document executed by both parties.
+</p>
+
+<p>
+ If the foregoing is acceptable to you, please sign this and the duplicate original of this Letter where
+ indicated below and return it to me at the above address.
+</p>
+
+<p>
+ Sincerely,<br>
+ ZEND TECHNOLOGIES, LTD.
+</p>
+
+<?php site_footer(['sidebar' => $SIDEBAR_DATA]);
diff --git a/mailing-lists.php b/mailing-lists.php
index 4b6dc60e1e..744e402bf7 100644
--- a/mailing-lists.php
+++ b/mailing-lists.php
@@ -287,7 +287,7 @@ function output_lists_table($mailing_lists): void
     foreach ($mailing_lists as $listinfo) {
         if (!is_array($listinfo)) {
             echo "<tr><th>{$listinfo}</th><th>Moderated</th><th>Archive</th>" .
- "<th>Newsgroup</th><th>Normal</th><th>Digest</th></tr>\n";
+ "<th>Newsgroup</th><th>Normal</th><th>Digest</th><th>List name</th></tr>\n";
         } else {
             echo '<tr align="center">';
             echo '<td align="left"><strong>' . $listinfo[1] . '</strong> <small>&lt;<a href="mailto:’ . $listinfo[0] . '@lists.php.net">' . $listinfo[0] . '@lists.php.net</a>&gt;</small><br><small>' . $listinfo[2] . '</small></td>';
@@ -303,6 +303,7 @@ function output_lists_table($mailing_lists): void
             echo '<td>' . ($listinfo[6] ? "<a href=\"news://news.php.net/{$listinfo[6]}\">yes</a> <a href=\"http://news.php.net/group.php?group=\{$listinfo\[6\]\}\\&quot;&gt;http&lt;/a&gt;&quot; : 'n/a') . '</td>';
             echo '<td><input name="maillist" type="radio" value="' . $listinfo[0] . '"></td>';
             echo '<td>' . ($listinfo[5] ? '<input name="maillist" type="radio" value="' . $listinfo[0] . '-digest">' : 'n/a') . '</td>';
+ echo '<td><code><small>' . $listinfo[0] . '</small></code></td>';
             echo "</tr>\n";
         }
     }
@@ -349,48 +350,57 @@ function output_lists_table($mailing_lists): void

<p>
  If you experience trouble subscribing via the form above, you may also
- subscribe by sending an email to the list server.
- To subscribe to any mailing list, send an email to
- <code><em>listname</em>+subscribe@lists.php.net</code>
- (substituting the name of the list for <code><em>listname</em></code>
- &mdash; for example, <code>php-general+subscribe@lists.php.net</code>).
+ subscribe by sending an email to the list server. To subscribe to any
+ mailing list, send an email to
+ <code><em>listname</em><b>+subscribe</b>@lists.php.net</code> (substituting the
+ name of the list for <code><em>listname</em></code>&mdash;for example,
+ <a href="mailto:php-general+subscribe@lists.php.net"><code>php-general+subscribe@lists.php.net</code></a>).
</p>

<h2>Mailing list options</h2>

<p>
- All of the mailing lists hosted at <a
- href="http://lists.php.net/&quot;&gt;lists\.php\.net&lt;/a&gt; are managed using the <a
- href="http://mlmmj.org/&quot;&gt;mlmmj&lt;/a&gt; mailing list software.
- There are a variety of commands you can use to modify your subscription.
- For a full overview, send a message to <code>php-whatever+help@lists.php.net</code> (as in,
- <code>php-general+help@lists.php.net</code>).</a>
+ All the mailing lists hosted at <a href="http://lists.php.net/&quot;&gt;lists\.php\.net&lt;/a&gt;
+ are managed using the <a href="http://mlmmj.org/&quot;&gt;mlmmj&lt;/a&gt; mailing list
+ software. There are a variety of commands you may use to modify your
+ subscription. For a full overview, send a message to
+ <code><em>listname</em><b>+help</b>@lists.php.net</code> (as in,
+ <a href="mailto:php-general+help@lists.php.net"><code>php-general+help@lists.php.net</code></a>).
</p>

<h3>Subscribing</h3>

<ul>
- <li>The normal mailing list, where you receive every message seperately:<br/>
- Email: <code>php-<em>listname</em>+subscribe@lists.php.net</code></li>
- <li>The daily digest list, where you receive an email with every message for a whole day at once:<br/>
- Email: <code>php-<em>listname</em>+subscribe<b>-digest</b>@lists.php.net</code></li>
- <li>The no email list, where you receive no emails from the list, but you can still post to it:<br/>
- Email: <code>php-<em>listname</em>+subscribe<b>-nomail</b>@lists.php.net</code></li>
+ <li>The normal mailing list, where you receive every message separately:<br/>
+ Email: <code><em>listname</em><b>+subscribe</b>@lists.php.net</code></li>
+ <li>The daily digest list, where you receive a daily email with every message for the whole day:<br/>
+ Email: <code><em>listname</em><b>+subscribe-digest</b>@lists.php.net</code></li>
+ <li>The "no email" list, where you receive no emails from the list, but you have permission to post to it:<br/>
+ Email: <code><em>listname</em><b>+subscribe-nomail</b>@lists.php.net</code></li>
</ul>

<h3>Unsubscribing</h3>

<p>
-Email: <code>php-<em>listname</em>+unsubscribe@lists.php.net</code>
+ To unsubscribe from a mailing list, send an email to
+ <code><em>listname</em><b>+unsubscribe</b>@lists.php.net</code>, where
+ <em>listname</em> is the name of the list you wish to unsubscribe from.
+ For example, to unsubscribe from the <code>php-announce</code> mailing list,
+ send an email to <a href="mailto:php-announce+unsubscribe@lists.php.net">
+ <code>php-announce+unsubscribe@lists.php.net</code></a>.
+</p>
+
+<p>
+ Please note, you must send the email from the address you want to unsubscribe.
</p>

<h3>Help</h3>

<ul>
- <li>For a FAQ (Frequently Asked Questions):<br/>
- Email: <code>php-<em>listname</em>+help@lists.php.net</code></li>
- <li>To reach an administrator:<br/>
- Email: <code>php-<em>listname</em>+owner@lists.php.net</code></li>
+ <li>For mailing list FAQs (Frequently Asked Questions):<br/>
+ Email: <code><em>listname</em><b>+help</b>@lists.php.net</code></li>
+ <li>To reach an administrator:<br/>
+ Email: <code><em>listname</em><b>+owner</b>@lists.php.net</code></li>
</ul>

diff --git a/releases/8_1_33.php b/releases/8_1_33.php
new file mode 100644
index 0000000000..8fadb7715a
--- /dev/null
+++ b/releases/8_1_33.php
@@ -0,0 +1,16 @@
+<?php
+$_SERVER['BASE_PAGE'] = 'releases/8_1_33.php';
+include_once __DIR__ . '/../include/prepend.inc';
+site_header('PHP 8.1.33 Release Announcement');
+?>
+<h1>PHP 8.1.33 Release Announcement</h1>
+
+<p>The PHP development team announces the immediate availability of PHP 8.1.33. This is a security release.</p>
+
+<p>All PHP 8.1 users are encouraged to upgrade to this version.</p>
+
+<p>For source downloads of PHP 8.1.33 please visit our <a href="PHP: Manual Quick Reference page</a>,
+Windows source and binaries can be found on <a href="https://windows.php.net/download/&quot;&gt;windows\.php\.net/download/&lt;/a&gt;\.
+The list of changes is recorded in the <a href="PHP: PHP 8 ChangeLog.
+</p>
+<?php site_footer();
diff --git a/releases/8_2_29.php b/releases/8_2_29.php
new file mode 100644
index 0000000000..8c605a2c8b
--- /dev/null
+++ b/releases/8_2_29.php
@@ -0,0 +1,16 @@
+<?php
+$_SERVER['BASE_PAGE'] = 'releases/8_2_29.php';
+include_once __DIR__ . '/../include/prepend.inc';
+site_header('PHP 8.2.29 Release Announcement');
+?>
+<h1>PHP 8.2.29 Release Announcement</h1>
+
+<p>The PHP development team announces the immediate availability of PHP 8.2.29. This is a security release.</p>
+
+<p>All PHP 8.2 users are encouraged to upgrade to this version.</p>
+
+<p>For source downloads of PHP 8.2.29 please visit our <a href="PHP: Manual Quick Reference page</a>,
+Windows source and binaries can be found on <a href="https://windows.php.net/download/&quot;&gt;windows\.php\.net/download/&lt;/a&gt;\.
+The list of changes is recorded in the <a href="PHP: PHP 8 ChangeLog.
+</p>
+<?php site_footer();
diff --git a/releases/8_3_23.php b/releases/8_3_23.php
new file mode 100644
index 0000000000..c8b1427cbb
--- /dev/null
+++ b/releases/8_3_23.php
@@ -0,0 +1,16 @@
+<?php
+$_SERVER['BASE_PAGE'] = 'releases/8_3_23.php';
+include_once __DIR__ . '/../include/prepend.inc';
+site_header('PHP 8.3.23 Release Announcement');
+?>
+<h1>PHP 8.3.23 Release Announcement</h1>
+
+<p>The PHP development team announces the immediate availability of PHP 8.3.23. This is a security release.</p>
+
+<p>All PHP 8.3 users are encouraged to upgrade to this version.</p>
+
+<p>For source downloads of PHP 8.3.23 please visit our <a href="PHP: Manual Quick Reference page</a>,
+Windows source and binaries can be found on <a href="https://windows.php.net/download/&quot;&gt;windows\.php\.net/download/&lt;/a&gt;\.
+The list of changes is recorded in the <a href="https://www.php.net/ChangeLog-8.php#8.3.23&quot;&gt;ChangeLog&lt;/a&gt;\.
+</p>
+<?php site_footer();
diff --git a/releases/8_4_10.php b/releases/8_4_10.php
new file mode 100644
index 0000000000..638a6a8abc
--- /dev/null
+++ b/releases/8_4_10.php
@@ -0,0 +1,18 @@
+<?php
+$_SERVER['BASE_PAGE'] = 'releases/8_4_10.php';
+include_once __DIR__ . '/../include/prepend.inc';
+site_header('PHP 8.4.10 Release Announcement');
+?>
+<h1>PHP 8.4.10 Release Announcement</h1>
+
+<p>The PHP development team announces the immediate availability of PHP 8.4.10. This is a security release.</p>
+
+<p>Version 8.4.9 was skipped because it was tagged without including security patches.</p>
+
+<p>All PHP 8.4 users are encouraged to upgrade to this version.</p>
+
+<p>For source downloads of PHP 8.4.10 please visit our <a href="PHP: Manual Quick Reference page</a>,
+Windows source and binaries can be found on <a href="https://windows.php.net/download/&quot;&gt;windows\.php\.net/download/&lt;/a&gt;\.
+The list of changes is recorded in the <a href="PHP: PHP 8 ChangeLog.
+</p>
+<?php site_footer();
diff --git a/search.php b/search.php
index 45f719fef1..05874deaa0 100644
--- a/search.php
+++ b/search.php
@@ -52,7 +52,7 @@
         "href" => $MYSITE . "phpnetimprovedsearch.src",
         "title" => "Add PHP.net search",
     ];
- site_header("Search", ["link" => [$link], "current" => "help"]);
+ site_header("Search", ["link" => [$link], "current" => "help", 'css' => 'cse-search.css']);

     google_cse();
     site_footer();
diff --git a/src/News/NewsHandler.php b/src/News/NewsHandler.php
new file mode 100644
index 0000000000..a7e97f766e
--- /dev/null
+++ b/src/News/NewsHandler.php
@@ -0,0 +1,81 @@
+<?php
+
+declare(strict_types=1);
+
+namespace phpweb\News;
+
+use DateTimeImmutable;
+
+use function array_filter;
+use function array_values;
+use function is_array;
+
+final class NewsHandler
+{
+ private const MAX_FRONT_PAGE_NEWS = 25;
+
+ public function getLastestNews(): array|null
+ {
+ $news = $this->getPregeneratedNews();
+ if (!isset($news[0])) {
+ return null;
+ }
+
+ return $news[0];
+ }
+
+ /** @return list<array> */
+ public function getFrontPageNews(): array
+ {
+ $frontPage = ;
+ foreach ($this->getPregeneratedNews() as $entry) {
+ foreach ($entry['category'] as $category) {
+ if ($category['term'] !== 'frontpage') {
+ continue;
+ }
+
+ $frontPage = $entry;
+ if (count($frontPage) >= self::MAX_FRONT_PAGE_NEWS) {
+ break 2;
+ }
+ }
+ }
+
+ return $frontPage;
+ }
+
+ /** @return list<array> */
+ public function getConferences(): array
+ {
+ $conferences = ;
+ foreach ($this->getPregeneratedNews() as $entry) {
+ foreach ($entry['category'] as $category) {
+ if ($category['term'] !== 'cfp' && $category['term'] !== 'conferences') {
+ continue;
+ }
+
+ $conferences = $entry;
+ break;
+ }
+ }
+
+ return $conferences;
+ }
+
+ /** @return list<array> */
+ public function getNewsByYear(int $year): array
+ {
+ return array_values(array_filter(
+ $this->getPregeneratedNews(),
+ static fn (array $entry): bool => (int) (new DateTimeImmutable($entry['published']))->format('Y') === $year,
+ ));
+ }
+
+ public function getPregeneratedNews(): array
+ {
+ $NEWS_ENTRIES = null;
+ include __DIR__ . '/../../include/pregen-news.inc';
+
+ return is_array($NEWS_ENTRIES) ? $NEWS_ENTRIES : ;
+ }
+}
diff --git a/styles/cse-search.css b/styles/cse-search.css
new file mode 100644
index 0000000000..45d3879b39
--- /dev/null
+++ b/styles/cse-search.css
@@ -0,0 +1,237 @@
+/* {{{ Search results. */
+
+/* Undo a whole bunch of default styles. */
+#layout .cse .gsc-control-cse,
+#layout .gsc-control-cse,
+#layout .gsc-control-cse .gsc-table-result {
+ font-family: var(--font-family-sans-serif);
+ font-size: 1rem;
+ margin: 0;
+ padding: 0;
+ position: relative;
+}
+
+/* Override the search box styling. */
+#layout .cse form.gsc-search-box,
+#layout form.gsc-search-box {
+ margin: 0 0 1rem 0;
+ padding: 0;
+}
+
+#layout .cse table.gsc-search-box,
+#layout table.gsc-search-box {
+ border: solid 1px #99c;
+ border-radius: 2px;
+}
+
+#layout .cse input.gsc-input,
+#layout input.gsc-input {
+ border: 0;
+}
+
+#layout .cse table.gsc-search-box td,
+#layout table.gsc-search-box td {
+ padding-right: unset;
+}
+
+#layout .cse table.gsc-search-box .gsc-search-button,
+#layout table.gsc-search-box .gsc-search-button {
+ margin-left: unset;
+}
+
+#layout .cse input.gsc-search-button,
+#layout input.gsc-search-button {
+ background: #99c;
+ border: solid 1px #99c;
+ border-radius: 0;
+ color: rgb(238, 238, 255);
+}
+
+#layout .cse input.gsc-search-button:hover,
+#layout input.gsc-search-button:hover {
+ color: white;
+}
+
+/* We don't need a clear button. */
+#layout .cse .gsc-clear-button,
+#layout .gsc-clear-button {
+ display: none;
+}
+
+/* Style the "tabs", and reformat them as a sidebar item. */
+#layout .cse div.gsc-results-wrapper-visible,
+#layout div.gsc-results-wrapper-visible {
+ position: relative;
+ min-height: 11rem;
+}
+
+#layout .cse .gsc-tabsArea,
+#layout .gsc-tabsArea {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 23.404%;
+ margin-right: 2.762%;
+ padding: .5rem .75rem;
+ border: 1px solid #e0e0e0;
+ background-color: #f2f2f2;
+ border-bottom-color: #d9d9d9;
+ border-radius: 2px;
+ margin-top: 0;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+#layout .cse .gsc-tabHeader.gsc-tabhActive,
+#layout .gsc-tabHeader.gsc-tabhActive,
+#layout .cse .gsc-tabHeader.gsc-tabhInactive,
+#layout .gsc-tabHeader.gsc-tabhInactive {
+ background: transparent;
+ color: rgb(38, 38, 38);
+ border: 0;
+ display: block;
+ font-size: 100%;
+ font-weight: normal;
+ border-top: dotted 1px rgb(189, 189, 189);
+ padding: 0;
+}
+
+#layout .cse .gsc-tabHeader.gsc-tabhActive:first-child,
+#layout .gsc-tabHeader.gsc-tabhActive:first-child,
+#layout .cse .gsc-tabHeader.gsc-tabhInactive:first-child,
+#layout .gsc-tabHeader.gsc-tabhInactive:first-child {
+ border: 0;
+}
+
+#layout .cse .gsc-tabHeader.gsc-tabhActive,
+#layout .gsc-tabHeader.gsc-tabhActive {
+ color: black;
+}
+
+#layout .cse .gsc-tabHeader.gsc-tabhActive:after,
+#layout .gsc-tabHeader.gsc-tabhActive:after {
+ content: "»";
+ color: black;
+ float: right;
+ text-align: right;
+}
+
+#layout .cse .gsc-tabHeader.gsc-tabhInactive:hover,
+#layout .gsc-tabHeader.gsc-tabhInactive:hover {
+ color: #693;
+}
+
+/* Format the results in the right place. */
+#layout .cse .gsc-above-wrapper-area,
+#layout .gsc-above-wrapper-area {
+ border: 0;
+}
+
+#layout .cse .gsc-above-wrapper-area-container,
+#layout .gsc-above-wrapper-area-container {
+ width: 100%;
+}
+
+#layout .cse .gsc-orderby,
+#layout .gsc-orderby {
+ padding: 0 4px;
+}
+
+#layout .cse .gsc-result-info-container,
+#layout .gsc-result-info-container {
+ padding: 0;
+ margin: 0;
+ vertical-align: inherit;
+}
+
+#layout .cse .gsc-result-info,
+#layout .gsc-result-info {
+ color: var(--dark-grey-color);
+ font-size: 0.75rem;
+ padding: 0;
+ margin: 0;
+}
+
+#layout .cse .gsc-resultsHeader,
+#layout .gsc-resultsHeader {
+ display: none;
+}
+
+#layout .cse .gsc-webResult.gsc-result,
+#layout .gsc-webResult.gsc-result {
+ margin: 0 0 1rem 0;
+ padding: 0;
+ border: 0;
+}
+
+#layout .cse .gs-webResult.gs-result a,
+#layout .gs-webResult.gs-result a,
+#layout .cse .gs-webResult.gs-result a b,
+#layout .gs-webResult.gs-result a b {
+ border-bottom: solid 1px rgb(51, 102, 153);
+ color: rgb(51, 102, 153);
+ text-decoration: none;
+}
+
+#layout .cse .gs-webResult.gs-result a:focus,
+#layout .gs-webResult.gs-result a:focus,
+#layout .cse .gs-webResult.gs-result a:hover,
+#layout .gs-webResult.gs-result a:hover,
+#layout .cse .gs-webResult.gs-result a:focus b,
+#layout .gs-webResult.gs-result a:focus b,
+#layout .cse .gs-webResult.gs-result a:hover b,
+#layout .gs-webResult.gs-result a:hover b {
+ border-bottom-color: rgb(51, 102, 153);
+ color: rgb(102, 153, 51);
+}
+
+#layout .gs-webResult.gs-result .gs-visibleUrl {
+ font-weight: normal;
+}
+
+/* Handle no results tabs. */
+#layout .gs-no-results-result .gs-snippet {
+ border: 0;
+ background: transparent;
+}
+
+/* Override docs table styling we don't want. */
+.docs #cse th,
+.docs #cse td {
+ padding: 0;
+}
+
+/* }}} */
+
+@media only screen and (max-width: 760px), (min-device-width: 768px) and (max-device-width: 1024px) {
+ tr {
+ margin: 0;
+ display: table-row;
+ }
+
+ td:before {
+ content: none;
+ }
+
+ table {
+ display: table;
+ }
+
+ thead {
+ display: table-header-group;
+ }
+
+ tbody {
+ display: table-row-group;
+ }
+
+ td:not(.gsc-clear-button),
+ th {
+ display: table-cell;
+ }
+
+ .gssb_a {
+ padding: 5px 3px !important;
+ white-space: normal !important;
+ }
+}
diff --git a/styles/theme-base.css b/styles/theme-base.css
index 298be51d16..59b4ad6329 100644
--- a/styles/theme-base.css
+++ b/styles/theme-base.css
@@ -715,209 +715,6 @@ table.standard th.subr {
     text-align: right;
}

-/* {{{ Search results. */
-
-/* Undo a whole bunch of default styles. */
-#layout .cse .gsc-control-cse,
-#layout .gsc-control-cse,
-#layout .gsc-control-cse .gsc-table-result {
- font-family: var(--font-family-sans-serif);
- font-size: 1rem;
- margin: 0;
- padding: 0;
- position: relative;
-}
-
-/* Override the search box styling. */
-#layout .cse form.gsc-search-box,
-#layout form.gsc-search-box {
- margin: 0 0 1rem 0;
- padding: 0;
-}
-
-#layout .cse table.gsc-search-box,
-#layout table.gsc-search-box {
- border: solid 1px #99c;
- border-radius: 2px;
-}
-
-#layout .cse input.gsc-input,
-#layout input.gsc-input {
- border: 0;
-}
-
-#layout .cse table.gsc-search-box td,
-#layout table.gsc-search-box td {
- padding: 0;
-}
-
-#layout .cse input.gsc-search-button,
-#layout input.gsc-search-button {
- background: #99c;
- border: solid 1px #99c;
- border-radius: 0;
- color: rgb(238, 238, 255);
-}
-
-#layout .cse input.gsc-search-button:hover,
-#layout input.gsc-search-button:hover {
- color: white;
-}
-
-/* We don't need a clear button. */
-#layout .cse .gsc-clear-button,
-#layout .gsc-clear-button {
- display: none;
-}
-
-/* Style the "tabs", and reformat them as a sidebar item. */
-#layout .cse div.gsc-results-wrapper-visible,
-#layout div.gsc-results-wrapper-visible {
- position: relative;
- min-height: 11rem;
-}
-
-#layout .cse .gsc-tabsArea,
-#layout .gsc-tabsArea {
- position: absolute;
- top: 0;
- left: 0;
- width: 23.404%;
- margin-right: 2.762%;
- padding:.5rem .75rem;
- border: 1px solid #e0e0e0;
- background-color:#f2f2f2;
- border-bottom-color:#d9d9d9;
- border-radius:2px;
- margin-top: 0;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
-}
-
-#layout .cse .gsc-tabHeader.gsc-tabhActive,
-#layout .gsc-tabHeader.gsc-tabhActive,
-#layout .cse .gsc-tabHeader.gsc-tabhInactive,
-#layout .gsc-tabHeader.gsc-tabhInactive {
- background: transparent;
- color: rgb(38, 38, 38);
- border: 0;
- display: block;
- font-size: 100%;
- font-weight: normal;
- border-top: dotted 1px rgb(189, 189, 189);
- padding: 0;
-}
-
-#layout .cse .gsc-tabHeader.gsc-tabhActive:first-child,
-#layout .gsc-tabHeader.gsc-tabhActive:first-child,
-#layout .cse .gsc-tabHeader.gsc-tabhInactive:first-child,
-#layout .gsc-tabHeader.gsc-tabhInactive:first-child {
- border: 0;
-}
-
-#layout .cse .gsc-tabHeader.gsc-tabhActive,
-#layout .gsc-tabHeader.gsc-tabhActive {
- color: black;
-}
-
-#layout .cse .gsc-tabHeader.gsc-tabhActive:after,
-#layout .gsc-tabHeader.gsc-tabhActive:after {
- content: "»";
- color: black;
- float: right;
- text-align: right;
-}
-
-#layout .cse .gsc-tabHeader.gsc-tabhInactive:hover,
-#layout .gsc-tabHeader.gsc-tabhInactive:hover {
- color: #693;
-}
-
-/* Format the results in the right place. */
-#layout .cse .gsc-above-wrapper-area,
-#layout .gsc-above-wrapper-area {
- border: 0;
- margin: 0;
- padding: 0 0 1rem 26.166%;
- width: 73.834%;
-}
-
-#layout .cse .gsc-above-wrapper-area-container,
-#layout .gsc-above-wrapper-area-container {
- width: auto;
-}
-
-#layout .cse .gsc-result-info-container,
-#layout .gsc-result-info-container {
- padding: 0;
- margin: 0;
-}
-
-#layout .cse .gsc-result-info,
-#layout .gsc-result-info {
- color: var(--dark-grey-color);
- font-size: 0.75rem;
- padding: 0;
- margin: 0;
-}
-
-#layout .cse .gsc-results,
-#layout .gsc-results {
- margin: 0;
- padding: 0 0 0 26.166%;
- width: 73.834%;
-}
-
-#layout .cse .gsc-resultsHeader,
-#layout .gsc-resultsHeader {
- display: none;
-}
-
-#layout .cse .gsc-webResult.gsc-result,
-#layout .gsc-webResult.gsc-result {
- margin: 0 0 1rem 0;
- padding: 0;
- border: 0;
-}
-
-#layout .cse .gs-webResult.gs-result a,
-#layout .gs-webResult.gs-result a,
-#layout .cse .gs-webResult.gs-result a b,
-#layout .gs-webResult.gs-result a b {
- border-bottom: solid 1px rgb(51, 102, 153);
- color: rgb(51, 102, 153);
- text-decoration: none;
-}
-
-#layout .cse .gs-webResult.gs-result a:focus,
-#layout .gs-webResult.gs-result a:focus,
-#layout .cse .gs-webResult.gs-result a:hover,
-#layout .gs-webResult.gs-result a:hover,
-#layout .cse .gs-webResult.gs-result a:focus b,
-#layout .gs-webResult.gs-result a:focus b,
-#layout .cse .gs-webResult.gs-result a:hover b,
-#layout .gs-webResult.gs-result a:hover b {
- border-bottom-color: rgb(51, 102, 153);
- color: rgb(102, 153, 51);
-}
-
-#layout .gs-webResult.gs-result .gs-visibleUrl {
- font-weight: normal;
-}
-
-/* Handle no results tabs. */
-#layout .gs-no-results-result .gs-snippet {
- border: 0;
- background: transparent;
-}
-
-/* Override docs table styling we don't want. */
-.docs #cse th,
-.docs #cse td {
- padding: 0;
-}
-/* }}} */
-
div.informalexample {
     margin: .75rem 0;
}
diff --git a/tests/Unit/News/NewsHandlerTest.php b/tests/Unit/News/NewsHandlerTest.php
new file mode 100644
index 0000000000..25df5f7e77
--- /dev/null
+++ b/tests/Unit/News/NewsHandlerTest.php
@@ -0,0 +1,57 @@
+<?php
+
+declare(strict_types=1);
+
+namespace News;
+
+use DateTimeImmutable;
+use PHPUnit\Framework\Attributes\CoversClass;
+use PHPUnit\Framework\TestCase;
+use phpweb\News\NewsHandler;
+
+#[CoversClass(NewsHandler::class)]
+final class NewsHandlerTest extends TestCase
+{
+ public function testGetLastestNews(): void
+ {
+ $newsHandler = new NewsHandler();
+ $news = $newsHandler->getPregeneratedNews();
+ self::assertArrayHasKey(0, $news);
+ self::assertSame($news[0], $newsHandler->getLastestNews());
+ }
+
+ public function testGetConferences(): void
+ {
+ $conferences = (new NewsHandler())->getConferences();
+ self::assertNotEmpty($conferences);
+ foreach ($conferences as $conference) {
+ $isConference = false;
+ foreach ($conference['category'] as $category) {
+ if ($category['term'] === 'cfp' || $category['term'] === 'conferences') {
+ $isConference = true;
+ break;
+ }
+ }
+
+ self::assertTrue($isConference);
+ }
+ }
+
+ public function testGetNewsByYear(): void
+ {
+ $news = (new NewsHandler())->getNewsByYear(2018);
+ self::assertNotEmpty($news);
+ foreach ($news as $entry) {
+ self::assertSame('2018', (new DateTimeImmutable($entry['published']))->format('Y'));
+ }
+ }
+
+ public function testGetFrontPageNews(): void
+ {
+ $frontPage = (new NewsHandler())->getFrontPageNews();
+ self::assertCount(25, $frontPage);
+ foreach ($frontPage as $news) {
+ self::assertContains(['term' => 'frontpage', 'label' => 'PHP.net frontpage news'], $news['category']);
+ }
+ }
+}