Add Symfony’s polyfill for PHP 8.4
authorAlexander Ebert <ebert@woltlab.com>
Thu, 9 Jan 2025 12:41:43 +0000 (13:41 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Thu, 9 Jan 2025 12:41:43 +0000 (13:41 +0100)
14 files changed:
wcfsetup/install/files/lib/system/api/composer.json
wcfsetup/install/files/lib/system/api/composer.lock
wcfsetup/install/files/lib/system/api/composer/autoload_classmap.php
wcfsetup/install/files/lib/system/api/composer/autoload_files.php
wcfsetup/install/files/lib/system/api/composer/autoload_psr4.php
wcfsetup/install/files/lib/system/api/composer/autoload_static.php
wcfsetup/install/files/lib/system/api/composer/installed.json
wcfsetup/install/files/lib/system/api/composer/installed.php
wcfsetup/install/files/lib/system/api/symfony/polyfill-php84/LICENSE [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/symfony/polyfill-php84/Php84.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/symfony/polyfill-php84/README.md [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/symfony/polyfill-php84/Resources/stubs/Deprecated.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/symfony/polyfill-php84/bootstrap.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/symfony/polyfill-php84/composer.json [new file with mode: 0644]

index 6ddedcf74f2e161ed52c043bd8c2c5980e32fb6c..bf7351b960213fa6ab00e55cd78fc877d7d4d992 100644 (file)
@@ -33,6 +33,7 @@
     "sebastian/diff": "^5.1.1",
     "symfony/polyfill-php82": "^1.31.0",
     "symfony/polyfill-php83": "^1.31",
+    "symfony/polyfill-php84": "^1.31",
     "willdurand/negotiation": "^3.1"
   },
   "replace": {
index d2831968736af3aa71264084a40be0f31e0f8296..988957d54c5c53305afb2f7edb46cc93365e326a 100644 (file)
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "e28f08e0dd80e8d2c529f7e098d220ba",
+    "content-hash": "ad149cda0b5a871e0b2e6555fa9ecd72",
     "packages": [
         {
             "name": "brick/math",
             ],
             "time": "2024-09-09T11:45:10+00:00"
         },
+        {
+            "name": "symfony/polyfill-php84",
+            "version": "v1.31.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-php84.git",
+                "reference": "e5493eb51311ab0b1cc2243416613f06ed8f18bd"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/e5493eb51311ab0b1cc2243416613f06ed8f18bd",
+                "reference": "e5493eb51311ab0b1cc2243416613f06ed8f18bd",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Php84\\": ""
+                },
+                "classmap": [
+                    "Resources/stubs"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-php84/tree/v1.31.0"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2024-09-09T12:04:04+00:00"
+        },
         {
             "name": "web-token/jwt-library",
             "version": "3.4.6",
index 32344845fd8da269ec58dc88dd90bee28f360a62..07994b1d956b0ab20cc75d4d50b221e6d22cd8b8 100644 (file)
@@ -401,6 +401,7 @@ return array(
     'DateMalformedStringException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateMalformedStringException.php',
     'DateObjectError' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateObjectError.php',
     'DateRangeError' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateRangeError.php',
+    'Deprecated' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Deprecated.php',
     'FastRoute\\BadRouteException' => $vendorDir . '/nikic/fast-route/src/BadRouteException.php',
     'FastRoute\\Cache' => $vendorDir . '/nikic/fast-route/src/Cache.php',
     'FastRoute\\Cache\\FileCache' => $vendorDir . '/nikic/fast-route/src/Cache/FileCache.php',
@@ -1629,6 +1630,7 @@ return array(
     'Symfony\\Polyfill\\Php82\\Random\\Engine\\Secure' => $vendorDir . '/symfony/polyfill-php82/Random/Engine/Secure.php',
     'Symfony\\Polyfill\\Php82\\SensitiveParameterValue' => $vendorDir . '/symfony/polyfill-php82/SensitiveParameterValue.php',
     'Symfony\\Polyfill\\Php83\\Php83' => $vendorDir . '/symfony/polyfill-php83/Php83.php',
+    'Symfony\\Polyfill\\Php84\\Php84' => $vendorDir . '/symfony/polyfill-php84/Php84.php',
     'Webmozart\\Assert\\Assert' => $vendorDir . '/webmozart/assert/src/Assert.php',
     'Webmozart\\Assert\\InvalidArgumentException' => $vendorDir . '/webmozart/assert/src/InvalidArgumentException.php',
     'Webmozart\\Assert\\Mixin' => $vendorDir . '/webmozart/assert/src/Mixin.php',
index 17123805051addd74838f7d23029b297b00929ff..71cbd0b8eaed9e8be4bd6a4f98b72ea69da03707 100644 (file)
@@ -21,4 +21,5 @@ return array(
     '253c157292f75eb38082b5acb06f3f01' => $vendorDir . '/nikic/fast-route/src/functions.php',
     '5897ea0ac4cccf14d323035e65887801' => $vendorDir . '/symfony/polyfill-php82/bootstrap.php',
     '662a729f963d39afe703c9d9b7ab4a8c' => $vendorDir . '/symfony/polyfill-php83/bootstrap.php',
+    '9d2b9fc6db0f153a0a149fefb182415e' => $vendorDir . '/symfony/polyfill-php84/bootstrap.php',
 );
index 8fd7f94482d23b7976c6c55284e69ca6a324b1ea..f3705b830b73ebebee0e9d96260176b65478a3e2 100644 (file)
@@ -7,6 +7,7 @@ $baseDir = $vendorDir;
 
 return array(
     'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
+    'Symfony\\Polyfill\\Php84\\' => array($vendorDir . '/symfony/polyfill-php84'),
     'Symfony\\Polyfill\\Php83\\' => array($vendorDir . '/symfony/polyfill-php83'),
     'Symfony\\Polyfill\\Php82\\' => array($vendorDir . '/symfony/polyfill-php82'),
     'Symfony\\Component\\CssSelector\\' => array($vendorDir . '/symfony/css-selector'),
index 01277c330041f416ee2386147338a53075472354..08fc90330dda0ea61e51de6d2baf9074b7a99ad0 100644 (file)
@@ -22,6 +22,7 @@ class ComposerStaticInita1f5f7c74275d47a45049a2936db1d0d
         '253c157292f75eb38082b5acb06f3f01' => __DIR__ . '/..' . '/nikic/fast-route/src/functions.php',
         '5897ea0ac4cccf14d323035e65887801' => __DIR__ . '/..' . '/symfony/polyfill-php82/bootstrap.php',
         '662a729f963d39afe703c9d9b7ab4a8c' => __DIR__ . '/..' . '/symfony/polyfill-php83/bootstrap.php',
+        '9d2b9fc6db0f153a0a149fefb182415e' => __DIR__ . '/..' . '/symfony/polyfill-php84/bootstrap.php',
     );
 
     public static $prefixLengthsPsr4 = array (
@@ -31,6 +32,7 @@ class ComposerStaticInita1f5f7c74275d47a45049a2936db1d0d
         ),
         'S' => 
         array (
+            'Symfony\\Polyfill\\Php84\\' => 23,
             'Symfony\\Polyfill\\Php83\\' => 23,
             'Symfony\\Polyfill\\Php82\\' => 23,
             'Symfony\\Component\\CssSelector\\' => 30,
@@ -97,6 +99,10 @@ class ComposerStaticInita1f5f7c74275d47a45049a2936db1d0d
         array (
             0 => __DIR__ . '/..' . '/webmozart/assert/src',
         ),
+        'Symfony\\Polyfill\\Php84\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/symfony/polyfill-php84',
+        ),
         'Symfony\\Polyfill\\Php83\\' => 
         array (
             0 => __DIR__ . '/..' . '/symfony/polyfill-php83',
@@ -638,6 +644,7 @@ class ComposerStaticInita1f5f7c74275d47a45049a2936db1d0d
         'DateMalformedStringException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateMalformedStringException.php',
         'DateObjectError' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateObjectError.php',
         'DateRangeError' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateRangeError.php',
+        'Deprecated' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Deprecated.php',
         'FastRoute\\BadRouteException' => __DIR__ . '/..' . '/nikic/fast-route/src/BadRouteException.php',
         'FastRoute\\Cache' => __DIR__ . '/..' . '/nikic/fast-route/src/Cache.php',
         'FastRoute\\Cache\\FileCache' => __DIR__ . '/..' . '/nikic/fast-route/src/Cache/FileCache.php',
@@ -1866,6 +1873,7 @@ class ComposerStaticInita1f5f7c74275d47a45049a2936db1d0d
         'Symfony\\Polyfill\\Php82\\Random\\Engine\\Secure' => __DIR__ . '/..' . '/symfony/polyfill-php82/Random/Engine/Secure.php',
         'Symfony\\Polyfill\\Php82\\SensitiveParameterValue' => __DIR__ . '/..' . '/symfony/polyfill-php82/SensitiveParameterValue.php',
         'Symfony\\Polyfill\\Php83\\Php83' => __DIR__ . '/..' . '/symfony/polyfill-php83/Php83.php',
+        'Symfony\\Polyfill\\Php84\\Php84' => __DIR__ . '/..' . '/symfony/polyfill-php84/Php84.php',
         'Webmozart\\Assert\\Assert' => __DIR__ . '/..' . '/webmozart/assert/src/Assert.php',
         'Webmozart\\Assert\\InvalidArgumentException' => __DIR__ . '/..' . '/webmozart/assert/src/InvalidArgumentException.php',
         'Webmozart\\Assert\\Mixin' => __DIR__ . '/..' . '/webmozart/assert/src/Mixin.php',
index 0ab45fc931e4120163c96f24d7c806c43c1a25ff..12710195bfcf94599193818f334b4b8192c1e1ed 100644 (file)
             ],
             "install-path": "../symfony/polyfill-php83"
         },
+        {
+            "name": "symfony/polyfill-php84",
+            "version": "v1.31.0",
+            "version_normalized": "1.31.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-php84.git",
+                "reference": "e5493eb51311ab0b1cc2243416613f06ed8f18bd"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/e5493eb51311ab0b1cc2243416613f06ed8f18bd",
+                "reference": "e5493eb51311ab0b1cc2243416613f06ed8f18bd",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2"
+            },
+            "time": "2024-09-09T12:04:04+00:00",
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "installation-source": "dist",
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Php84\\": ""
+                },
+                "classmap": [
+                    "Resources/stubs"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-php84/tree/v1.31.0"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "install-path": "../symfony/polyfill-php84"
+        },
         {
             "name": "web-token/jwt-library",
             "version": "3.4.6",
index 8985adda91f9c395ac34943a9997bb2793edba81..e058f9a1e9f05ec2710da177e736cd7aeba29770 100644 (file)
@@ -3,7 +3,7 @@
         'name' => '__root__',
         'pretty_version' => '6.1.x-dev',
         'version' => '6.1.9999999.9999999-dev',
-        'reference' => '7e305277c70cb69c4d566d99c44eef497f6614a1',
+        'reference' => 'f6d552ab096fab333bc496eab61b60fbf1adb6f5',
         'type' => 'project',
         'install_path' => __DIR__ . '/../',
         'aliases' => array(),
@@ -13,7 +13,7 @@
         '__root__' => array(
             'pretty_version' => '6.1.x-dev',
             'version' => '6.1.9999999.9999999-dev',
-            'reference' => '7e305277c70cb69c4d566d99c44eef497f6614a1',
+            'reference' => 'f6d552ab096fab333bc496eab61b60fbf1adb6f5',
             'type' => 'project',
             'install_path' => __DIR__ . '/../',
             'aliases' => array(),
             'aliases' => array(),
             'dev_requirement' => false,
         ),
+        'symfony/polyfill-php84' => array(
+            'pretty_version' => 'v1.31.0',
+            'version' => '1.31.0.0',
+            'reference' => 'e5493eb51311ab0b1cc2243416613f06ed8f18bd',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/polyfill-php84',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
         'web-token/jwt-key-mgmt' => array(
             'dev_requirement' => false,
             'replaced' => array(
diff --git a/wcfsetup/install/files/lib/system/api/symfony/polyfill-php84/LICENSE b/wcfsetup/install/files/lib/system/api/symfony/polyfill-php84/LICENSE
new file mode 100644 (file)
index 0000000..e374a5c
--- /dev/null
@@ -0,0 +1,19 @@
+Copyright (c) 2024-present Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/wcfsetup/install/files/lib/system/api/symfony/polyfill-php84/Php84.php b/wcfsetup/install/files/lib/system/api/symfony/polyfill-php84/Php84.php
new file mode 100644 (file)
index 0000000..1bca70b
--- /dev/null
@@ -0,0 +1,172 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Polyfill\Php84;
+
+/**
+ * @author Ayesh Karunaratne <ayesh@aye.sh>
+ * @author Pierre Ambroise <pierre27.ambroise@gmail.com>
+ *
+ * @internal
+ */
+final class Php84
+{
+    public static function mb_ucfirst(string $string, ?string $encoding = null): string
+    {
+        if (null === $encoding) {
+            $encoding = mb_internal_encoding();
+        }
+
+        try {
+            $validEncoding = @mb_check_encoding('', $encoding);
+        } catch (\ValueError $e) {
+            throw new \ValueError(sprintf('mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding));
+        }
+
+        // BC for PHP 7.3 and lower
+        if (!$validEncoding) {
+            throw new \ValueError(sprintf('mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding));
+        }
+
+        $firstChar = mb_substr($string, 0, 1, $encoding);
+        $firstChar = mb_convert_case($firstChar, \MB_CASE_TITLE, $encoding);
+
+        return $firstChar.mb_substr($string, 1, null, $encoding);
+    }
+
+    public static function mb_lcfirst(string $string, ?string $encoding = null): string
+    {
+        if (null === $encoding) {
+            $encoding = mb_internal_encoding();
+        }
+
+        try {
+            $validEncoding = @mb_check_encoding('', $encoding);
+        } catch (\ValueError $e) {
+            throw new \ValueError(sprintf('mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding));
+        }
+
+        // BC for PHP 7.3 and lower
+        if (!$validEncoding) {
+            throw new \ValueError(sprintf('mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding));
+        }
+
+        $firstChar = mb_substr($string, 0, 1, $encoding);
+        $firstChar = mb_convert_case($firstChar, \MB_CASE_LOWER, $encoding);
+
+        return $firstChar.mb_substr($string, 1, null, $encoding);
+    }
+
+    public static function array_find(array $array, callable $callback)
+    {
+        foreach ($array as $key => $value) {
+            if ($callback($value, $key)) {
+                return $value;
+            }
+        }
+
+        return null;
+    }
+
+    public static function array_find_key(array $array, callable $callback)
+    {
+        foreach ($array as $key => $value) {
+            if ($callback($value, $key)) {
+                return $key;
+            }
+        }
+
+        return null;
+    }
+
+    public static function array_any(array $array, callable $callback): bool
+    {
+        foreach ($array as $key => $value) {
+            if ($callback($value, $key)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public static function array_all(array $array, callable $callback): bool
+    {
+        foreach ($array as $key => $value) {
+            if (!$callback($value, $key)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public static function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string
+    {
+        return self::mb_internal_trim('{^[%s]+|[%1$s]+$}Du', $string, $characters, $encoding, __FUNCTION__);
+    }
+
+    public static function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string
+    {
+        return self::mb_internal_trim('{^[%s]+}Du', $string, $characters, $encoding, __FUNCTION__);
+    }
+
+    public static function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string
+    {
+        return self::mb_internal_trim('{[%s]+$}Du', $string, $characters, $encoding, __FUNCTION__);
+    }
+
+    private static function mb_internal_trim(string $regex, string $string, ?string $characters, ?string $encoding, string $function): string
+    {
+        if (null === $encoding) {
+            $encoding = mb_internal_encoding();
+        }
+
+        try {
+            $validEncoding = @mb_check_encoding('', $encoding);
+        } catch (\ValueError $e) {
+            throw new \ValueError(sprintf('%s(): Argument #3 ($encoding) must be a valid encoding, "%s" given', $function, $encoding));
+        }
+
+        // BC for PHP 7.3 and lower
+        if (!$validEncoding) {
+            throw new \ValueError(sprintf('%s(): Argument #3 ($encoding) must be a valid encoding, "%s" given', $function, $encoding));
+        }
+
+        if ('' === $characters) {
+            return null === $encoding ? $string : mb_convert_encoding($string, $encoding);
+        }
+
+        if ('UTF-8' === $encoding || \in_array(strtolower($encoding), ['utf-8', 'utf8'], true)) {
+            $encoding = 'UTF-8';
+        }
+
+        $string = mb_convert_encoding($string, 'UTF-8', $encoding);
+
+        if (null !== $characters) {
+            $characters = mb_convert_encoding($characters, 'UTF-8', $encoding);
+        }
+
+        if (null === $characters) {
+            $characters = "\\0 \f\n\r\t\v\u{00A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{2028}\u{2029}\u{202F}\u{205F}\u{3000}\u{0085}\u{180E}";
+        } else {
+            $characters = preg_quote($characters);
+        }
+
+        $string = preg_replace(sprintf($regex, $characters), '', $string);
+
+        if ('UTF-8' === $encoding) {
+            return $string;
+        }
+
+        return mb_convert_encoding($string, $encoding, 'UTF-8');
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/symfony/polyfill-php84/README.md b/wcfsetup/install/files/lib/system/api/symfony/polyfill-php84/README.md
new file mode 100644 (file)
index 0000000..bd56cdc
--- /dev/null
@@ -0,0 +1,17 @@
+Symfony Polyfill / Php84
+========================
+
+This component provides features added to PHP 8.4 core:
+
+- [`mb_ucfirst` and `mb_lcfirst`](https://wiki.php.net/rfc/mb_ucfirst)
+- [`array_find`, `array_find_key`, `array_any` and `array_all`](https://wiki.php.net/rfc/array_find)
+- [`Deprecated`](https://wiki.php.net/rfc/deprecated_attribute)
+- `CURL_HTTP_VERSION_3` and `CURL_HTTP_VERSION_3ONLY` constants
+
+More information can be found in the
+[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).
+
+License
+=======
+
+This library is released under the [MIT license](LICENSE).
diff --git a/wcfsetup/install/files/lib/system/api/symfony/polyfill-php84/Resources/stubs/Deprecated.php b/wcfsetup/install/files/lib/system/api/symfony/polyfill-php84/Resources/stubs/Deprecated.php
new file mode 100644 (file)
index 0000000..f3e6a4f
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+if (\PHP_VERSION_ID < 80400) {
+    #[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION | Attribute::TARGET_CLASS_CONSTANT)]
+    final class Deprecated
+    {
+        public readonly ?string $message;
+        public readonly ?string $since;
+
+        public function __construct(?string $message = null, ?string $since = null)
+        {
+            $this->message = $message;
+            $this->since = $since;
+        }
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/symfony/polyfill-php84/bootstrap.php b/wcfsetup/install/files/lib/system/api/symfony/polyfill-php84/bootstrap.php
new file mode 100644 (file)
index 0000000..73fb1f4
--- /dev/null
@@ -0,0 +1,62 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Polyfill\Php84 as p;
+
+if (\PHP_VERSION_ID >= 80400) {
+    return;
+}
+
+if (defined('CURL_VERSION_HTTP3') || PHP_VERSION_ID < 80200 && function_exists('curl_version') && curl_version()['version'] >= 0x074200) { // libcurl >= 7.66.0
+    define('CURL_HTTP_VERSION_3', 30);
+
+    if (defined('CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256')) { // libcurl >= 7.80.0 (7.88 would be better but is slow to check)
+        define('CURL_HTTP_VERSION_3ONLY', 31);
+    }
+}
+
+if (!function_exists('array_find')) {
+    function array_find(array $array, callable $callback) { return p\Php84::array_find($array, $callback); }
+}
+
+if (!function_exists('array_find_key')) {
+    function array_find_key(array $array, callable $callback) { return p\Php84::array_find_key($array, $callback); }
+}
+
+if (!function_exists('array_any')) {
+    function array_any(array $array, callable $callback): bool { return p\Php84::array_any($array, $callback); }
+}
+
+if (!function_exists('array_all')) {
+    function array_all(array $array, callable $callback): bool { return p\Php84::array_all($array, $callback); }
+}
+
+if (extension_loaded('mbstring')) {
+    if (!function_exists('mb_ucfirst')) {
+        function mb_ucfirst($string, ?string $encoding = null): string { return p\Php84::mb_ucfirst($string, $encoding); }
+    }
+
+    if (!function_exists('mb_lcfirst')) {
+        function mb_lcfirst($string, ?string $encoding = null): string { return p\Php84::mb_lcfirst($string, $encoding); }
+    }
+
+    if (!function_exists('mb_trim')) {
+        function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Php84::mb_trim($string, $characters, $encoding); }
+    }
+
+    if (!function_exists('mb_ltrim')) {
+        function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Php84::mb_ltrim($string, $characters, $encoding); }
+    }
+
+    if (!function_exists('mb_rtrim')) {
+        function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Php84::mb_rtrim($string, $characters, $encoding); }
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/symfony/polyfill-php84/composer.json b/wcfsetup/install/files/lib/system/api/symfony/polyfill-php84/composer.json
new file mode 100644 (file)
index 0000000..8bbc281
--- /dev/null
@@ -0,0 +1,33 @@
+{
+    "name": "symfony/polyfill-php84",
+    "type": "library",
+    "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
+    "keywords": ["polyfill", "shim", "compatibility", "portable"],
+    "homepage": "https://symfony.com",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Nicolas Grekas",
+            "email": "p@tchwork.com"
+        },
+        {
+            "name": "Symfony Community",
+            "homepage": "https://symfony.com/contributors"
+        }
+    ],
+    "require": {
+        "php": ">=7.2"
+    },
+    "autoload": {
+        "psr-4": { "Symfony\\Polyfill\\Php84\\": "" },
+        "files": [ "bootstrap.php" ],
+        "classmap": [ "Resources/stubs" ]
+    },
+    "minimum-stability": "dev",
+    "extra": {
+        "thanks": {
+            "name": "symfony/polyfill",
+            "url": "https://github.com/symfony/polyfill"
+        }
+    }
+}