diff --git a/app/code/Magento/Developer/Console/Command/DiInfoCommand.php b/app/code/Magento/Developer/Console/Command/DiInfoCommand.php index 75d9e56e1196e..81390d06df6b1 100644 --- a/app/code/Magento/Developer/Console/Command/DiInfoCommand.php +++ b/app/code/Magento/Developer/Console/Command/DiInfoCommand.php @@ -7,15 +7,26 @@ namespace Magento\Developer\Console\Command; use Magento\Developer\Model\Di\Information; +use Magento\Framework\ObjectManagerInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Magento\Framework\App\AreaList; +use Magento\Framework\App\Area; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class DiInfoCommand extends Command { + /** + * @var ObjectManagerInterface + */ + private ObjectManagerInterface $objectManager; + /** * Command name */ @@ -26,18 +37,34 @@ class DiInfoCommand extends Command */ public const CLASS_NAME = 'class'; + /** + * Area name + */ + public const AREA_CODE = 'area'; + /** * @var Information */ - private $diInformation; + private Information $diInformation; + + /** + * @var AreaList + */ + private AreaList $areaList; /** * @param Information $diInformation + * @param ObjectManagerInterface $objectManager + * @param AreaList|null $areaList */ public function __construct( - Information $diInformation + Information $diInformation, + ObjectManagerInterface $objectManager, + ?AreaList $areaList = null ) { $this->diInformation = $diInformation; + $this->objectManager = $objectManager; + $this->areaList = $areaList ?? \Magento\Framework\App\ObjectManager::getInstance()->get(AreaList::class); parent::__construct(); } @@ -49,10 +76,11 @@ public function __construct( protected function configure() { $this->setName(self::COMMAND_NAME) - ->setDescription('Provides information on Dependency Injection configuration for the Command.') - ->setDefinition([ - new InputArgument(self::CLASS_NAME, InputArgument::REQUIRED, 'Class name') - ]); + ->setDescription('Provides information on Dependency Injection configuration for the Command.') + ->setDefinition([ + new InputArgument(self::CLASS_NAME, InputArgument::REQUIRED, 'Class name'), + new InputArgument(self::AREA_CODE, InputArgument::OPTIONAL, 'Area Code') + ]); parent::configure(); } @@ -154,10 +182,14 @@ private function printPlugins($className, $output, $label) */ protected function execute(InputInterface $input, OutputInterface $output) { + $area = $input->getArgument(self::AREA_CODE) ?? Area::AREA_GLOBAL; + if ($area !== Area::AREA_GLOBAL) { + $this->setDiArea($area); + } $className = $input->getArgument(self::CLASS_NAME); $output->setDecorated(true); $output->writeln(''); - $output->writeln(sprintf('DI configuration for the class %s in the GLOBAL area', $className)); + $output->writeln(sprintf('DI configuration for the class %s in the %s area', $className, strtoupper($area))); if ($this->diInformation->isVirtualType($className)) { $output->writeln( @@ -173,4 +205,39 @@ protected function execute(InputInterface $input, OutputInterface $output) return \Magento\Framework\Console\Cli::RETURN_SUCCESS; } + + /** + * Set Area for DI Configuration + * + * @param string $area + * @return void + * @throws \InvalidArgumentException + */ + private function setDiArea(string $area): void + { + if ($this->validateAreaCodeFromInput($area)) { + $areaOmConfiguration = $this->objectManager + ->get(\Magento\Framework\App\ObjectManager\ConfigLoader::class) + ->load($area); + + $this->objectManager->configure($areaOmConfiguration); + + $this->objectManager->get(\Magento\Framework\Config\ScopeInterface::class) + ->setCurrentScope($area); + } else { + throw new InvalidArgumentException(sprintf('The "%s" area code does not exist', $area)); + } + } + + /** + * Validate Input + * + * @param string $area + * @return bool + */ + private function validateAreaCodeFromInput($area): bool + { + $availableAreaCodes = $this->areaList->getCodes(); + return in_array($area, $availableAreaCodes, true); + } } diff --git a/dev/tests/integration/testsuite/Magento/Developer/Console/Command/DiInfoCommandTest.php b/dev/tests/integration/testsuite/Magento/Developer/Console/Command/DiInfoCommandTest.php new file mode 100644 index 0000000000000..080c512786246 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Developer/Console/Command/DiInfoCommandTest.php @@ -0,0 +1,146 @@ +objectManager = Bootstrap::getObjectManager(); + $this->informationMock = $this->createMock(Information::class); + $this->areaListMock = $this->createMock(AreaList::class); + $this->command = new DiInfoCommand($this->informationMock, $this->objectManager, $this->areaListMock); + } + + /** + * @return void + */ + public function testExecuteWithGlobalArea(): void + { + $this->informationMock->expects($this->any()) + ->method('getPreference') + ->with('Magento\Framework\App\RouterList') + ->willReturn('Magento\Framework\App\RouterList'); + + $this->informationMock->expects($this->any()) + ->method('getParameters') + ->with('Magento\Framework\App\RouterList') + ->willReturn([ + ['objectManager', 'Magento\Framework\ObjectManagerInterface', null], + ['routerList', null, null] + ]); + + $this->informationMock->expects($this->once()) + ->method('getVirtualTypes') + ->with('Magento\Framework\App\RouterList') + ->willReturn([]); + + $this->informationMock->expects($this->any()) + ->method('getPlugins') + ->with('Magento\Framework\App\RouterList') + ->willReturn([ + 'before' => [], + 'around' => [], + 'after' => [] + ]); + + $commandTester = new CommandTester($this->command); + $commandTester->execute( + [ + DiInfoCommand::CLASS_NAME => "Magento\Framework\App\RouterList", + DiInfoCommand::AREA_CODE => null + ], + ); + $this->assertStringContainsString( + 'DI configuration for the class Magento\Framework\App\RouterList in the GLOBAL area', + $commandTester->getDisplay() + ); + } + + /** + * @return void + */ + public function testExecuteWithAreaCode(): void + { + $className = "Magento\Framework\App\RouterList"; + $this->informationMock->expects($this->any()) + ->method('getPreference') + ->with($className) + ->willReturn($className); + + $this->informationMock->expects($this->any()) + ->method('getParameters') + ->with($className) + ->willReturn([ + ['objectManager', 'Magento\Framework\ObjectManagerInterface', null], + ['routerList', null, null] + ]); + + $this->informationMock->expects($this->once()) + ->method('getVirtualTypes') + ->with($className) + ->willReturn([]); + + $this->informationMock->expects($this->any()) + ->method('getPlugins') + ->with($className) + ->willReturn([ + 'before' => [], + 'around' => [], + 'after' => [] + ]); + + $this->areaListMock->expects($this->once()) + ->method('getCodes') + ->willReturn(['frontend', 'adminhtml']); + + $commandTester = new CommandTester($this->command); + $commandTester->execute( + [ + DiInfoCommand::CLASS_NAME => "$className", + DiInfoCommand::AREA_CODE => "adminhtml" + ], + ); + + $this->assertStringContainsString( + "DI configuration for the class $className in the ADMINHTML area", + $commandTester->getDisplay() + ); + } +}