Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TASK] Deprecate old command configuration file #745

Merged
merged 1 commit into from Dec 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions .gitignore
@@ -1,10 +1,10 @@
/.Build/*
/Classes/Console/Hook/*
/Configuration/Console/ComposerPackagesCommands.php
/Configuration/ComposerPackagesCommands.php
/Libraries/vendor
/Resources/Public/*

/.php_cs.cache
/composer.lock
/ext_*
*GENERATED*
*GENERATED*
Expand Up @@ -49,11 +49,14 @@ public function run(ScriptEvent $event): bool
// Since meta packages have no code, thus cannot include any commands, we ignore them as well.
continue;
}
$commandConfiguration = array_merge($commandConfiguration, $this->getConfigFromPackage($installPath, $packageName));
$packageConfig = $this->getConfigFromPackage($installPath, $packageName);
if ($packageConfig !== []) {
$commandConfiguration[] = $packageConfig;
}
}

$success = file_put_contents(
__DIR__ . '/../../../../Configuration/Console/ComposerPackagesCommands.php',
__DIR__ . '/../../../../Configuration/ComposerPackagesCommands.php',
'<?php' . chr(10)
. 'return '
. var_export($commandConfiguration, true)
Expand Down Expand Up @@ -86,6 +89,7 @@ private function getConfigFromPackage(string $installPath, string $packageName):
{
$commandConfiguration = [];
if (file_exists($commandConfigurationFile = $installPath . '/Configuration/Console/Commands.php')) {
trigger_error($packageName . ': Configuration/Console/Commands.php for registering commands is deprecated and will be removed with 6.0. Register Symfony commands in Configuration/Commands.php instead.', E_USER_DEPRECATED);
$commandConfiguration = require $commandConfigurationFile;
}
if (file_exists($commandConfigurationFile = $installPath . '/Configuration/Commands.php')) {
Expand All @@ -96,6 +100,6 @@ private function getConfigFromPackage(string $installPath, string $packageName):
}
CommandConfiguration::ensureValidCommandRegistration($commandConfiguration, $packageName);

return [$packageName => CommandConfiguration::unifyCommandConfiguration($commandConfiguration, $packageName)];
return CommandConfiguration::unifyCommandConfiguration($commandConfiguration, $packageName);
}
}
1 change: 1 addition & 0 deletions Classes/Console/Core/Booting/Sequence.php
Expand Up @@ -84,6 +84,7 @@ public function removeStep($stepIdentifier)
* Executes all steps of this sequence
*
* @param Bootstrap $bootstrap
* @throws StepFailedException
* @return void
*/
public function invoke(Bootstrap $bootstrap)
Expand Down
8 changes: 1 addition & 7 deletions Classes/Console/Error/ExceptionHandler.php
Expand Up @@ -28,16 +28,10 @@ class ExceptionHandler
*/
protected $output;

/**
* @param ConsoleOutput $output
*/
public function __construct(ExceptionRenderer $exceptionRenderer = null, ConsoleOutput $output = null)
{
$this->exceptionRenderer = $exceptionRenderer ?: new ExceptionRenderer();
if ($output === null) {
$output = new ConsoleOutput(ConsoleOutput::VERBOSITY_DEBUG);
}
$this->output = $output;
$this->output = $output ?? new ConsoleOutput(ConsoleOutput::VERBOSITY_DEBUG);
}

/**
Expand Down
41 changes: 29 additions & 12 deletions Classes/Console/Mvc/Cli/CommandCollection.php
Expand Up @@ -53,6 +53,11 @@ class CommandCollection implements CommandLoaderInterface
*/
private $commands = [];

/**
* @var string[]
*/
private $replaces = [];

public function __construct(RunLevel $runLevel, CommandConfiguration $commandConfiguration)
{
$this->runLevel = $runLevel;
Expand Down Expand Up @@ -106,11 +111,11 @@ public function get($name): BaseCommand
throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name), [], 1518812618);
}
$commandConfig = $this->commands[$name];
if (isset($commandConfig['class'])) {
if (isset($commandConfig['controller'])) {
$command = GeneralUtility::makeInstance(CommandControllerCommand::class, $commandConfig['name'], new Command($commandConfig['controller'], $commandConfig['controllerCommandName']), $commandConfig['lateCommand'] ?? false);
} elseif (isset($commandConfig['class'])) {
/** @var BaseCommand $command */
$command = GeneralUtility::makeInstance($commandConfig['class'], $commandConfig['name']);
} elseif (isset($commandConfig['controller'])) {
$command = GeneralUtility::makeInstance(CommandControllerCommand::class, $commandConfig['name'], new Command($commandConfig['controller'], $commandConfig['controllerCommandName']));
} else {
throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name), [], 1520205204);
}
Expand Down Expand Up @@ -155,9 +160,22 @@ private function isCommandAvailable(string $name): bool

private function populateCommands(array $definitions = null)
{
foreach ($definitions ?? $this->commandConfiguration->getCommandDefinitions() as $nameSpacedName => $commandConfig) {
$this->add($nameSpacedName, $commandConfig);
$definitions = $definitions ?? $this->commandConfiguration->getCommandDefinitions();
$this->extractReplaces($definitions);
foreach ($definitions as $commandConfig) {
$this->add($commandConfig);
}
}

private function extractReplaces(array $definitions)
{
$replaces = [];
foreach ($definitions as $commandConfiguration) {
if (isset($commandConfiguration['replace'])) {
$replaces[] = $commandConfiguration['replace'];
}
}
$this->replaces = array_merge($this->replaces, ...$replaces);
}

private function initializeRunLevel()
Expand All @@ -174,25 +192,24 @@ private function initializeRunLevel()
}
}

private function add(string $nameSpacedName, array $commandConfig)
private function add(array $commandConfig)
{
$finalCommandName = $commandConfig['name'];
$replaces = $this->commandConfiguration->getReplaces();
if (in_array($commandConfig['name'], $replaces, true)
|| in_array($nameSpacedName, $replaces, true)
if (in_array($commandConfig['name'], $this->replaces, true)
|| in_array($commandConfig['nameSpacedName'], $this->replaces, true)
) {
return;
}
if (isset($this->commands[$finalCommandName])) {
$finalCommandName = $nameSpacedName;
$finalCommandName = $commandConfig['nameSpacedName'];
}
if (isset($this->commands[$finalCommandName])) {
throw new CommandNameAlreadyInUseException('Command "' . $finalCommandName . '" registered by "' . $commandConfig['vendor'] . '" is already in use', 1506531326);
}
$commandConfig['aliases'] = $commandConfig['aliases'] ?? [];
if ($finalCommandName !== $nameSpacedName) {
if ($finalCommandName !== $commandConfig['nameSpacedName']) {
// Add alias to be able to call this command always with name spaced command name
$commandConfig['aliases'][] = $nameSpacedName;
$commandConfig['aliases'][] = $commandConfig['nameSpacedName'];
}
$commandConfig['name'] = $finalCommandName;
$this->commands[$finalCommandName] = $commandConfig;
Expand Down
93 changes: 40 additions & 53 deletions Classes/Console/Mvc/Cli/CommandConfiguration.php
Expand Up @@ -15,7 +15,6 @@
*/

use Symfony\Component\Console\Exception\RuntimeException;
use TYPO3\CMS\Core\Console\CommandNameAlreadyInUseException;
use TYPO3\CMS\Core\Package\PackageInterface;
use TYPO3\CMS\Core\Package\PackageManager;

Expand All @@ -29,8 +28,6 @@ class CommandConfiguration
*/
private $packageManager;

private $replaces = [];

private $commandDefinitions = [];

public function __construct(PackageManager $packageManager)
Expand Down Expand Up @@ -60,40 +57,43 @@ public static function ensureValidCommandRegistration($commandConfiguration, $pa

public static function unifyCommandConfiguration(array $commandConfiguration, string $packageName): array
{
$commandDefinitions = array_replace($commandConfiguration['commands'] ?? [], self::extractCommandDefinitionsFromControllers($commandConfiguration['controllers'] ?? []));
$commandDefinitions = [];

foreach ($commandDefinitions as $commandName => $commandConfig) {
$commandDefinitions[$commandName]['vendor'] = $vendor = $commandConfig['vendor'] ?? $packageName;
foreach ($commandConfiguration['commands'] ?? [] as $commandName => $commandConfig) {
$vendor = $commandConfig['vendor'] ?? $packageName;
$nameSpacedCommandName = $vendor . ':' . $commandName;
$commandConfig['vendor'] = $vendor;
$commandConfig['name'] = $commandName;
$commandConfig['nameSpacedName'] = $nameSpacedCommandName;
$nameSpacedCommandCollection = $nameSpacedCommandName;
if (strrpos($commandName, ':') !== false) {
$nameSpacedCommandCollection = $vendor . ':' . substr($commandName, 0, strrpos($commandName, ':')) . ':*';
}
if (isset($commandConfiguration['runLevels'][$nameSpacedCommandCollection])) {
$commandDefinitions[$commandName]['runLevel'] = $commandConfiguration['runLevels'][$nameSpacedCommandCollection];
$commandConfig['runLevel'] = $commandConfiguration['runLevels'][$nameSpacedCommandCollection];
}
if (isset($commandConfiguration['runLevels'][$commandName])) {
$commandDefinitions[$commandName]['runLevel'] = $commandConfiguration['runLevels'][$commandName];
$commandConfig['runLevel'] = $commandConfiguration['runLevels'][$commandName];
}
if (isset($commandConfiguration['runLevels'][$nameSpacedCommandName])) {
$commandDefinitions[$commandName]['runLevel'] = $commandConfiguration['runLevels'][$nameSpacedCommandName];
$commandConfig['runLevel'] = $commandConfiguration['runLevels'][$nameSpacedCommandName];
}
if (isset($commandConfiguration['bootingSteps'][$commandName])) {
$commandDefinitions[$commandName]['bootingSteps'] = $commandConfiguration['bootingSteps'][$commandName];
$commandConfig['bootingSteps'] = $commandConfiguration['bootingSteps'][$commandName];
}
if (isset($commandConfiguration['bootingSteps'][$nameSpacedCommandName])) {
$commandDefinitions[$commandName]['bootingSteps'] = $commandConfiguration['bootingSteps'][$nameSpacedCommandName];
$commandConfig['bootingSteps'] = $commandConfiguration['bootingSteps'][$nameSpacedCommandName];
}
$commandDefinitions[] = $commandConfig;
}
if (isset($commandConfiguration['replace'])) {
$anyCommandName = key($commandDefinitions);
$commandDefinitions[$anyCommandName]['replace'] = array_merge($commandDefinitions[$anyCommandName]['replace'] ?? [], $commandConfiguration['replace']);
$commandDefinitions[0]['replace'] = array_merge($commandDefinitions[0]['replace'] ?? [], $commandConfiguration['replace']);
}

return $commandDefinitions;
return array_replace($commandDefinitions, self::extractCommandDefinitionsFromControllers($commandConfiguration['controllers'] ?? [], $packageName === '_lateCommands'));
}

private static function extractCommandDefinitionsFromControllers(array $controllers): array
private static function extractCommandDefinitionsFromControllers(array $controllers, bool $lateCommand): array
{
$commandDefinitions = [];
foreach ($controllers as $controllerClassName) {
Expand All @@ -113,24 +113,22 @@ private static function extractCommandDefinitionsFromControllers(array $controll
$vendor = \TYPO3\CMS\Core\Utility\GeneralUtility::camelCaseToLowerCaseUnderscored($classNameParts[1]);
$controllerCommandNameSpace = strtolower(substr($classNameParts[$numberOfClassNameParts - 1], 0, -17));
$commandName = $controllerCommandNameSpace . ':' . strtolower($controllerCommandName);
$commandDefinitions[$commandName]['vendor'] = $vendor;
$commandDefinitions[$commandName]['controller'] = $controllerClassName;
$commandDefinitions[$commandName]['controllerCommandName'] = $controllerCommandName;
$namespacedCommandName = $vendor . ':' . $commandName;
$commandDefinitions[] = [
'vendor' => $vendor,
'name' => $commandName,
'nameSpacedName' => $namespacedCommandName,
'controller' => $controllerClassName,
'controllerCommandName' => $controllerCommandName,
'lateCommand' => $lateCommand,
];
}
}
}

return $commandDefinitions;
}

/**
* @return array
*/
public function getReplaces(): array
{
return $this->replaces;
}

/**
* @return array
*/
Expand All @@ -141,55 +139,43 @@ public function getCommandDefinitions(): array

public function addCommandControllerCommands(array $commandControllers): array
{
$addedCommandDefinitions = $this->getCommandDefinitionsForCommands(self::unifyCommandConfiguration(['controllers' => $commandControllers], ''));
$this->commandDefinitions = array_replace($this->commandDefinitions, $addedCommandDefinitions);
$addedCommandDefinitions = self::unifyCommandConfiguration(['controllers' => $commandControllers], '_lateCommands');
$this->commandDefinitions = array_merge($this->commandDefinitions, $addedCommandDefinitions);

if (!empty($addedCommandDefinitions)) {
trigger_error('Registering commands via $GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'extbase\'][\'commandControllers\'] is deprecated and will be removed with 6.0. Register Symfony commands in Configuration/Commands.php instead.', E_USER_DEPRECATED);
}

return $addedCommandDefinitions;
}

private function initialize()
{
foreach ($this->gatherRawConfig() as $commandConfiguration) {
$this->commandDefinitions = array_replace($this->commandDefinitions, $this->getCommandDefinitionsForCommands($commandConfiguration));
}
}

private function getCommandDefinitionsForCommands(array $commands): array
{
$commandDefinitions = [];
foreach ($commands as $name => $singleCommandConfiguration) {
$vendor = $singleCommandConfiguration['vendor'];
if (isset($singleCommandConfiguration['replace'])) {
$this->replaces = array_merge($this->replaces, $singleCommandConfiguration['replace']);
}
$singleCommandConfiguration['name'] = $name;
$nameSpacedCommandName = $vendor . ':' . $name;
if (isset($this->commandDefinitions[$nameSpacedCommandName])) {
throw new CommandNameAlreadyInUseException('Command "' . $nameSpacedCommandName . '" registered by "' . $vendor . '" is already in use', 1520181870);
}
$commandDefinitions[$nameSpacedCommandName] = $singleCommandConfiguration;
}

return $commandDefinitions;
$this->commandDefinitions = array_merge([], ...$this->gatherRawConfig());
}

/**
* @return array
*/
private function gatherRawConfig(): array
{
if (file_exists($commandConfigurationFile = __DIR__ . '/../../../../Configuration/Console/ComposerPackagesCommands.php')) {
if (file_exists($commandConfigurationFile = __DIR__ . '/../../../../Configuration/ComposerPackagesCommands.php')) {
$configuration = require $commandConfigurationFile;
} else {
// We only reach this point in non composer mode
// We ensure that our commands are present, even if we are not an active extension or even not being an extension at all
$configuration['typo3_console'] = self::unifyCommandConfiguration(require __DIR__ . '/../../../../Configuration/Console/Commands.php', 'typo3_console');
$configuration[] = require __DIR__ . '/../../../../Configuration/Commands.php';
}
foreach ($this->packageManager->getActivePackages() as $package) {
if ($package->getPackageKey() === 'typo3_console') {
// We only reach this point in non composer mode
// We registered our commands above already
continue;
}
$packageConfig = $this->getConfigFromExtension($package);
if (!empty($packageConfig)) {
self::ensureValidCommandRegistration($packageConfig, $package->getPackageKey());
$configuration[$package->getPackageKey()] = self::unifyCommandConfiguration($packageConfig, $package->getPackageKey());
$configuration[] = self::unifyCommandConfiguration($packageConfig, $package->getPackageKey());
}
}

Expand All @@ -200,6 +186,7 @@ private function getConfigFromExtension(PackageInterface $package): array
{
$commandConfiguration = [];
if (file_exists($commandConfigurationFile = $package->getPackagePath() . 'Configuration/Console/Commands.php')) {
trigger_error('Configuration/Console/Commands.php for registering commands is deprecated and will be removed with 6.0. Register Symfony commands in Configuration/Commands.php instead.', E_USER_DEPRECATED);
$commandConfiguration = require $commandConfigurationFile;
}
if (file_exists($commandConfigurationFile = $package->getPackagePath() . 'Configuration/Commands.php')) {
Expand Down
Expand Up @@ -35,6 +35,7 @@
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Output\OutputInterface;

/**
Expand All @@ -60,10 +61,24 @@ class CommandControllerCommand extends Command
*/
private $application;

public function __construct($name, CommandDefinition $commandDefinition)
/**
* @var bool
*/
private $isLateCommand;

public function __construct($name, CommandDefinition $commandDefinition, bool $isLateCommand = false)
{
$this->commandDefinition = $commandDefinition;
parent::__construct($name);
$this->isLateCommand = $isLateCommand;
}

/**
* @return bool
*/
public function isLateCommand(): bool
{
return $this->isLateCommand;
}

public function getNativeDefinition()
Expand Down Expand Up @@ -155,9 +170,16 @@ protected function execute(InputInterface $input, OutputInterface $output)
{
// @deprecated in 5.0 will be removed in 6.0
$givenCommandName = $input->getArgument('command');
$debugOutput = $output;
if ($output instanceof ConsoleOutput) {
$debugOutput = $output->getErrorOutput();
}
if ($givenCommandName === $this->getAliases()[0]) {
$output->writeln('<warning>Specifying the full command name is deprecated.</warning>');
$output->writeln(sprintf('<warning>Please use "%s" as command name instead.</warning>', $this->getName()));
$debugOutput->writeln('<warning>Specifying the full command name is deprecated.</warning>');
$debugOutput->writeln(sprintf('<warning>Please use "%s" as command name instead.</warning>', $this->getName()));
}
if ($this->isLateCommand && $output->isVerbose()) {
$debugOutput->writeln('<warning>Registering commands via $GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'extbase\'][\'commandControllers\'] is deprecated and will be removed with 6.0. Register Symfony commands in Configuration/Commands.php instead.</warning>');
}
$response = (new RequestHandler())->handle($this->commandDefinition, $input, $output);

Expand Down