consolidation / robo

Modern task runner for PHP
http://robo.li
Other
2.67k stars 304 forks source link

Unable to delegate to a ReflectionContainer #1137

Open mikeshiyan opened 1 year ago

mikeshiyan commented 1 year ago

Steps to reproduce

I created the following executable file and ran it in terminal without any arguments:

#!/usr/bin/env php
<?php

use League\Container\ReflectionContainer;
use NasAutomation\Commands\RoboFile;
use Robo\Robo;
use Robo\Runner;

define('ROOT_DIR', dirname(__DIR__));

$class_loader = require ROOT_DIR . '/vendor/autoload.php';

$app_name = 'Nas Automation';
$app_version = 'dev';

$application = Robo::createDefaultApplication($app_name, $app_version);
$container = Robo::createContainer($application, NULL, $class_loader);

$container->delegate(new ReflectionContainer(TRUE));

Robo::finalizeContainer($container);

$runner = new Runner([RoboFile::class]);
$runner
  ->setContainer($container);

$status_code = $runner->execute($_SERVER['argv']);
exit($status_code);

Expected behavior

I expected to get the standard output, kind of:

Usage:
  command [options] [arguments]

Options:
  -h, --help ...

Actual behavior

Instead I get the fatal error:

PHP Fatal error:  Uncaught TypeError: Symfony\Component\Console\Style\SymfonyStyle::__construct(): Argument #1 ($input) must be of type Symfony\Component\Console\Input\InputInterface, League\Container\Argument\ResolvableArgument given in /home/m/Dropbox/dev/pets/nas_automation/vendor/symfony/console/Style/SymfonyStyle.php:48
Stack trace:
#0 [internal function]: Symfony\Component\Console\Style\SymfonyStyle->__construct()
#1 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/ReflectionContainer.php(58): ReflectionClass->newInstanceArgs()
#2 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Container.php(189): League\Container\ReflectionContainer->get()
#3 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Container.php(111): League\Container\Container->resolve()
#4 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Argument/ArgumentResolverTrait.php(45): League\Container\Container->get()
#5 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/Definition.php(218): League\Container\Definition\Definition->resolveArguments()
#6 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/Definition.php(179): League\Container\Definition\Definition->invokeMethods()
#7 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/Definition.php(154): League\Container\Definition\Definition->resolveNew()
#8 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/DefinitionAggregate.php(79): League\Container\Definition\Definition->resolve()
#9 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Container.php(161): League\Container\Definition\DefinitionAggregate->resolve()
#10 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Container.php(111): League\Container\Container->resolve()
#11 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Argument/ArgumentResolverTrait.php(45): League\Container\Container->get()
#12 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/Definition.php(218): League\Container\Definition\Definition->resolveArguments()
#13 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/Definition.php(179): League\Container\Definition\Definition->invokeMethods()
#14 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/Definition.php(154): League\Container\Definition\Definition->resolveNew()
#15 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/DefinitionAggregate.php(79): League\Container\Definition\Definition->resolve()
#16 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Container.php(161): League\Container\Definition\DefinitionAggregate->resolve()
#17 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Container.php(111): League\Container\Container->resolve()
#18 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Argument/ArgumentResolverTrait.php(45): League\Container\Container->get()
#19 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/Definition.php(218): League\Container\Definition\Definition->resolveArguments()
#20 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/Definition.php(179): League\Container\Definition\Definition->invokeMethods()
#21 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/Definition.php(154): League\Container\Definition\Definition->resolveNew()
#22 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Definition/DefinitionAggregate.php(79): League\Container\Definition\Definition->resolve()
#23 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Container.php(161): League\Container\Definition\DefinitionAggregate->resolve()
#24 /home/m/Dropbox/dev/pets/nas_automation/vendor/league/container/src/Container.php(111): League\Container\Container->resolve()
#25 /home/m/Dropbox/dev/pets/nas_automation/vendor/consolidation/robo/src/Runner.php(352): League\Container\Container->get()
#26 /home/m/Dropbox/dev/pets/nas_automation/vendor/consolidation/robo/src/Runner.php(319): Robo\Runner->registerCommandClass()
#27 /home/m/Dropbox/dev/pets/nas_automation/vendor/consolidation/robo/src/Runner.php(279): Robo\Runner->registerCommandClasses()
#28 /home/m/Dropbox/dev/pets/nas_automation/vendor/consolidation/robo/src/Runner.php(158): Robo\Runner->run()
#29 /home/m/Dropbox/dev/pets/nas_automation/bin/nas(27): Robo\Runner->execute()
#30 {main}
  thrown in /home/m/Dropbox/dev/pets/nas_automation/vendor/symfony/console/Style/SymfonyStyle.php on line 48

System Configuration

Linux, PHP 8.2.0, robo 4.0.3, league/container 4.2.0.

Proposed solution

There is a code in \Robo\Robo::configureContainer:

self::addShared($container, 'parameterInjection', \Consolidation\AnnotatedCommand\ParameterInjection::class)
    ->addMethodCall('register', ['Symfony\Component\Console\Style\SymfonyStyle', 'symfonyStyleInjector'])
    ->addMethodCall('register', ['Robo\Symfony\ConsoleIO', 'consoleIOInjector']);

Because the Symfony\Component\Console\Style\SymfonyStyle is a real class, the ReflectionContainer tries to instantiate it and fails. Anyway this is undesirable behavior - the register method uses 1st argument as an array key.

I propose to wrap these arguments (SymfonyStyle & ConsoleIO) in \League\Container\Argument\Literal\StringArgument objects. This way a container delegation works as expected.