box icon indicating copy to clipboard operation
box copied to clipboard

Symfony function polyfills get put into the wrong namespace

Open allejo opened this issue 2 years ago • 0 comments

Bug report

Question Answer
Box version 3.16.0
PHP version 7.4.21
Platform with version macOS
Github Repo allejo/rrlog @ feature/box-cleanup

When my box.json.dist uses the "KevinGH\\Box\\Compactor\\PhpScoper" compactor, any function that Symfony polyfills in the global namespace is written into the wrong namespace. Kinda hard to explain, so let me try my best.

In my project's vendor directory, the InputOption.php file makes use of str_starts_with, which exists in PHP 8.0+ but Symfony makes use of symfony/polyfills-php80 to polyfill this function, allowing it to work as intended.

namespace Symfony\Component\Console\Input;

class InputOption
{
    // ...

    public function __construct(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null)
    {
        if (str_starts_with($name, '--')) {
            $name = substr($name, 2);
        }

// ...

This works because symfony/polyfills-php80 has a bootstrap file that has this logic in the global namespace:

if (!function_exists('str_starts_with')) {
    function str_starts_with(?string $haystack, ?string $needle): bool { ... }
}

After running Box with PhpScoper, the InputOption.php file ends up with code that looks like,

namespace humbug12345\Symfony\Component\Console\Input;

class InputOption
{
    // ...

    public function __construct(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null)
    {
        if (\str_starts_with($name, '--')) { // <- Notice the `\` at the beginning of `str_starts_with()`
            $name = substr($name, 2);
        }

// ...

And symfony/polyfill-php80's bootstrap file has been updated to,

namespace humbug12345;

if (!function_exists('str_starts_with')) {
    function str_starts_with(?string $haystack, ?string $needle): bool { ... }
}

This leads to the str_starts_with() not being found since InputOption.php is referencing the one in the global namespace and the polyfill is being added to the scoped namespace.

box.json.dist
{
   "main": "bin/rrlog",
   "compression": "GZ",
   "compactors": [
       "KevinGH\\Box\\Compactor\\Php",
       "KevinGH\\Box\\Compactor\\PhpScoper"
   ],
   "datetime": "release-date",
   "git-version": "package_version",
   "output": "rrlog.phar"
}
Output
$ php -d display_errors=on rrlog.phar

Fatal error: Uncaught Error: Call to undefined function str_starts_with() in phar:///Users/allejo/Development/BZFlag/rrlog/rrlog.phar/vendor/symfony/console/Input/InputOption.php on line 20

Error: Call to undefined function str_starts_with() in phar:///Users/allejo/Development/BZFlag/rrlog/rrlog.phar/vendor/symfony/console/Input/InputOption.php on line 20

allejo avatar Apr 18 '22 08:04 allejo