diff --git a/config/di.php b/config/di.php index 83350623..09054a1a 100644 --- a/config/di.php +++ b/config/di.php @@ -15,7 +15,7 @@ return [ GiiInterface::class => function (Injector $injector) use ($params): GiiInterface { - $generatorsInstances = []; + $proxies = []; $generators = $params['yiisoft/yii-gii']['generators']; foreach ($generators as $generator) { @@ -27,9 +27,9 @@ fn() => $injector->make($class, $generator['parameters'] ?? []), $class, ); - $generatorsInstances[$class::getId()] = $loader; + $proxies[$class::getId()] = $loader; } - return new Gii($generatorsInstances); + return new Gii($proxies, []); }, ParametersProvider::class => [ 'class' => ParametersProvider::class, diff --git a/src/Controller/DefaultController.php b/src/Controller/DefaultController.php index 2c32a3d9..cce96e35 100644 --- a/src/Controller/DefaultController.php +++ b/src/Controller/DefaultController.php @@ -19,6 +19,7 @@ use Yiisoft\Yii\Gii\Exception\InvalidGeneratorCommandException; use Yiisoft\Yii\Gii\Generator\CommandHydrator; use Yiisoft\Yii\Gii\GeneratorCommandInterface; +use Yiisoft\Yii\Gii\GeneratorInterface; use Yiisoft\Yii\Gii\GeneratorProxy; use Yiisoft\Yii\Gii\GiiInterface; use Yiisoft\Yii\Gii\ParametersProvider; @@ -39,7 +40,14 @@ public function list(GiiInterface $gii): ResponseInterface return $this->responseFactory->createResponse([ 'generators' => array_map( $this->serializeGenerator(...), - array_values(array_map(fn(GeneratorProxy $proxy) => $proxy->getClass(), $generators)), + array_values( + array_map( + fn (GeneratorInterface|GeneratorProxy $generator) => $generator instanceof GeneratorProxy + ? $generator->getClass() + : $generator::class, + $generators + ) + ), ), ]); } diff --git a/src/GeneratorProxy.php b/src/GeneratorProxy.php index fc4b09cc..2ceec9ab 100644 --- a/src/GeneratorProxy.php +++ b/src/GeneratorProxy.php @@ -6,19 +6,19 @@ use Closure; -class GeneratorProxy +final class GeneratorProxy { private ?GeneratorInterface $generator = null; /** - * @psalm-param class-string $class + * @psalm-param class-string $class */ public function __construct(private readonly Closure $loader, private readonly string $class) { } /** - * @return class-string + * @return class-string */ public function getClass(): string { diff --git a/src/Gii.php b/src/Gii.php index 7fcdfa1c..c5f197a2 100644 --- a/src/Gii.php +++ b/src/Gii.php @@ -6,25 +6,29 @@ use Yiisoft\Yii\Gii\Exception\GeneratorNotFoundException; -/** - * @psalm-import-type LazyGenerator from GiiInterface - */ final class Gii implements GiiInterface { /** * @param array $proxies + * @param array $instances */ - public function __construct(private array $proxies) + public function __construct( + private readonly array $proxies, + private array $instances, + ) { } public function addGenerator(GeneratorInterface $generator): void { - $this->proxies[$generator::getId()] = new GeneratorProxy(fn () => $generator, $generator::class); + $this->instances[$generator::getId()] = $generator; } public function getGenerator(string $id): GeneratorInterface { + if (isset($this->instances[$id])) { + return $this->instances[$id]; + } return isset($this->proxies[$id]) ? $this->proxies[$id]->loadGenerator() : throw new GeneratorNotFoundException('Generator "' . $id . '" not found'); @@ -32,6 +36,9 @@ public function getGenerator(string $id): GeneratorInterface public function getGenerators(): array { - return $this->proxies; + return [ + ...$this->instances, + ...$this->proxies, + ]; } } diff --git a/src/GiiInterface.php b/src/GiiInterface.php index 614435d3..76d6fa4e 100644 --- a/src/GiiInterface.php +++ b/src/GiiInterface.php @@ -4,12 +4,8 @@ namespace Yiisoft\Yii\Gii; -use Closure; use Yiisoft\Yii\Gii\Exception\GeneratorNotFoundException; -/** - * @psalm-type LazyGenerator = Closure(): GeneratorInterface - */ interface GiiInterface { /** @@ -23,7 +19,7 @@ public function addGenerator(GeneratorInterface $generator): void; public function getGenerator(string $id): GeneratorInterface; /** - * @return GeneratorInterface[] + * @return GeneratorInterface[]|GeneratorProxy[] */ public function getGenerators(): array; } diff --git a/src/Validator/TemplateRuleHandler.php b/src/Validator/TemplateRuleHandler.php index b779f6ea..ab5ad734 100644 --- a/src/Validator/TemplateRuleHandler.php +++ b/src/Validator/TemplateRuleHandler.php @@ -12,6 +12,7 @@ use Yiisoft\Validator\ValidationContext; use Yiisoft\Yii\Gii\GeneratorCommandInterface; use Yiisoft\Yii\Gii\GeneratorInterface; +use Yiisoft\Yii\Gii\GeneratorProxy; use Yiisoft\Yii\Gii\GiiInterface; use Yiisoft\Yii\Gii\ParametersProvider; @@ -79,9 +80,12 @@ public function validate(mixed $value, object $rule, ValidationContext $context) private function getGenerator(GeneratorCommandInterface $dataSet): GeneratorInterface { foreach ($this->gii->getGenerators() as $generator) { - if ($generator::getCommandClass() === $dataSet::class) { + if ($generator instanceof GeneratorInterface && $generator::getCommandClass() === $dataSet::class) { return $generator; } + if ($generator instanceof GeneratorProxy && $generator->getClass()::getCommandClass() === $dataSet::class) { + return $generator->loadGenerator(); + } } throw new RuntimeException(sprintf('Unknown generator "%s".', $dataSet::class)); } diff --git a/tests/TestCase.php b/tests/TestCase.php index 9dfc3aa5..35019d00 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -28,6 +28,7 @@ use Yiisoft\Validator\Validator; use Yiisoft\Validator\ValidatorInterface; use Yiisoft\Yii\Gii\Generator as Generators; +use Yiisoft\Yii\Gii\GeneratorProxy; use Yiisoft\Yii\Gii\Gii; use Yiisoft\Yii\Gii\GiiInterface; @@ -54,15 +55,16 @@ protected function getContainer(array $definitions = []): ContainerInterface $config = ContainerConfig::create() ->withDefinitions([ GiiInterface::class => function (ContainerInterface $container) { - $generators = [ - Generators\Controller\Generator::getId() => Generators\Controller\Generator::class, - Generators\ActiveRecord\Generator::getId() => Generators\ActiveRecord\Generator::class, + $proxies = [ + Generators\Controller\Generator::getId() => new GeneratorProxy( + fn() => $container->get(Generators\Controller\Generator::class), + Generators\Controller\Generator::class, + ), ]; - $generatorsInstances = []; - foreach ($generators as $class) { - $generatorsInstances[] = $container->get($class); - } - return new Gii($generatorsInstances); + $instances = [ + Generators\ActiveRecord\Generator::getId() => $container->get(Generators\ActiveRecord\Generator::class), + ]; + return new Gii($proxies, $instances); }, Aliases::class => new Aliases( [