Skip to content

Commit 38121e3

Browse files
bnfhelhum
authored andcommitted
[FEATURE] Implement lazy console command list
Based on the configuration syntax of the Symfony Console feature symfony/symfony#39851 …but implemented differently, using a registry pattern rather then a lazy-object pattern (like symfony does). Main motiviation for the registry pattern is following: Symfony LazyCommand wrappers add quite some complexity only for the sake of the list command, we already got lazy commands (in terms of execution) as our CommandRegistry implements the ConfigurationLoaderInterface that has been introduced by 2017 to add support for lazy commands. Now, that means we already got a registry for lazy commands, so it is logical to add lazy description handling there as well. We want to assure that the command list will never instantiate any commands. This is in constrast to the Symfony core LazyCommand approach, where legacy commands, that do not provide a compile time description, would still be instantiated during console command list. Also commands that return false in `isEnabled()` are now listed. That means enabled state is only evaluated during runtime. Therefore the special `dumpautoload` command is transformed into a lowlevel command in order to be hidden dependending on being run in composer-mode or not. Releases: master Resolves: #93174 Change-Id: Ifa68404cc81c64a335be30f2263a7eb17de0624d Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/67635 Tested-by: TYPO3com <noreply@typo3.com> Tested-by: core-ci <typo3@b13.com> Tested-by: Benni Mack <benni@typo3.org> Tested-by: Helmut Hummel <typo3@helhum.io> Reviewed-by: Benni Mack <benni@typo3.org> Reviewed-by: Helmut Hummel <typo3@helhum.io>
1 parent daf0b2d commit 38121e3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+453
-93
lines changed

typo3/sysext/backend/Classes/Command/LockBackendCommand.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ class LockBackendCommand extends Command
3434
protected function configure()
3535
{
3636
$this
37-
->setDescription('Lock the TYPO3 Backend')
3837
->addArgument(
3938
'redirect',
4039
InputArgument::OPTIONAL,

typo3/sysext/backend/Classes/Command/ReferenceIndexUpdateCommand.php

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,12 @@ class ReferenceIndexUpdateCommand extends Command
3535
*/
3636
public function configure()
3737
{
38-
$this->setDescription('Update the reference index of TYPO3')
39-
->addOption(
40-
'check',
41-
'c',
42-
InputOption::VALUE_NONE,
43-
'Only check the reference index of TYPO3'
44-
);
38+
$this->addOption(
39+
'check',
40+
'c',
41+
InputOption::VALUE_NONE,
42+
'Only check the reference index of TYPO3'
43+
);
4544
}
4645

4746
/**

typo3/sysext/backend/Classes/Command/ResetPasswordCommand.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ public function __construct(Context $context, PasswordReset $passwordReset)
6060
protected function configure()
6161
{
6262
$this
63-
->setDescription('Trigger a password reset for a backend user.')
6463
->addArgument(
6564
'backendurl',
6665
InputArgument::REQUIRED,

typo3/sysext/backend/Classes/Command/UnlockBackendCommand.php

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,6 @@
2626
*/
2727
class UnlockBackendCommand extends Command
2828
{
29-
/**
30-
* Configure the command by defining the name, options and arguments
31-
*/
32-
protected function configure()
33-
{
34-
$this->setDescription('Unlock the TYPO3 Backend');
35-
}
36-
3729
/**
3830
* Executes the command for removing the lock file
3931
*

typo3/sysext/backend/Configuration/Services.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@ services:
99

1010
TYPO3\CMS\Backend\Command\LockBackendCommand:
1111
tags:
12-
- { name: 'console.command', command: 'backend:lock' }
12+
- { name: 'console.command', command: 'backend:lock', description: 'Lock the TYPO3 Backend' }
1313

1414
TYPO3\CMS\Backend\Command\UnlockBackendCommand:
1515
tags:
16-
- { name: 'console.command', command: 'backend:unlock' }
16+
- { name: 'console.command', command: 'backend:unlock', description: 'Unlock the TYPO3 Backend' }
1717

1818
TYPO3\CMS\Backend\Command\ReferenceIndexUpdateCommand:
1919
tags:
20-
- { name: 'console.command', command: 'referenceindex:update' }
20+
- { name: 'console.command', command: 'referenceindex:update', description: 'Update the reference index of TYPO3' }
2121

2222
TYPO3\CMS\Backend\Command\ResetPasswordCommand:
2323
tags:
24-
- { name: 'console.command', command: 'backend:resetpassword', schedulable: false }
24+
- { name: 'console.command', command: 'backend:resetpassword', description: 'Trigger a password reset for a backend user', schedulable: false }
2525

2626
TYPO3\CMS\Backend\Template\ModuleTemplate:
2727
shared: false
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the TYPO3 CMS project.
7+
*
8+
* It is free software; you can redistribute it and/or modify it under
9+
* the terms of the GNU General Public License, either version 2
10+
* of the License, or any later version.
11+
*
12+
* For the full copyright and license information, please read the
13+
* LICENSE.txt file that was distributed with this source code.
14+
*
15+
* The TYPO3 project - inspiring people to share!
16+
*/
17+
18+
namespace TYPO3\CMS\Core\Command\Descriptor;
19+
20+
use Symfony\Component\Console\Application;
21+
use Symfony\Component\Console\Descriptor\ApplicationDescription;
22+
use Symfony\Component\Console\Descriptor\TextDescriptor as SymfonyTextDescriptor;
23+
use Symfony\Component\Console\Helper\Helper;
24+
use Symfony\Component\Console\Input\InputDefinition;
25+
use TYPO3\CMS\Core\Console\CommandRegistry;
26+
27+
/**
28+
* Text descriptor.
29+
*
30+
* @internal
31+
*/
32+
class TextDescriptor extends SymfonyTextDescriptor
33+
{
34+
private CommandRegistry $commandRegistry;
35+
36+
public function __construct(CommandRegistry $commandRegistry)
37+
{
38+
$this->commandRegistry = $commandRegistry;
39+
}
40+
41+
/**
42+
* {@inheritdoc}
43+
*/
44+
protected function describeApplication(Application $application, array $options = [])
45+
{
46+
$describedNamespace = $options['namespace'] ?? null;
47+
$rawOutput = $options['raw_text'] ?? false;
48+
49+
$commands = $this->commandRegistry->filter($describedNamespace);
50+
51+
if ($rawOutput) {
52+
$width = $this->getColumnWidth(['' => ['commands' => array_keys($commands)]]);
53+
54+
foreach ($commands as $command) {
55+
$this->write(sprintf("%-{$width}s %s\n", $command['name'], strip_tags($command['description'])), true);
56+
}
57+
return;
58+
}
59+
60+
$namespaces = $this->commandRegistry->getNamespaces();
61+
$help = $application->getHelp();
62+
if ($help !== '') {
63+
$this->write($help . "\n\n", true);
64+
}
65+
66+
$this->write("<comment>Usage:</comment>\n", true);
67+
$this->write(" command [options] [arguments]\n\n");
68+
69+
$this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()));
70+
71+
$this->write("\n\n");
72+
73+
if ($describedNamespace) {
74+
$this->write(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), true);
75+
$namespace = $namespaces[$describedNamespace] ?? [];
76+
$width = $this->getColumnWidth(['' => $namespace]);
77+
$this->describeNamespace($namespace, $commands, $width);
78+
} else {
79+
$this->write('<comment>Available commands:</comment>', true);
80+
// calculate max. width based on available commands per namespace
81+
$width = $this->getColumnWidth($namespaces);
82+
foreach ($namespaces as $namespace) {
83+
if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
84+
$this->write("\n");
85+
$this->write(' <comment>' . $namespace['id'] . '</comment>', true);
86+
}
87+
$this->describeNamespace($namespace, $commands, $width);
88+
}
89+
}
90+
91+
$this->write("\n");
92+
}
93+
94+
private function describeNamespace(array $namespace, array $commands, int $width): void
95+
{
96+
foreach ($namespace['commands'] as $name) {
97+
$this->write("\n");
98+
$spacingWidth = $width - Helper::strlen($name);
99+
$command = $commands[$name];
100+
101+
$aliases = count($command['aliases']) ? '[' . implode('|', $command['aliases']) . '] ' : '';
102+
$this->write(sprintf(' <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $aliases . $command['description']), true);
103+
}
104+
}
105+
106+
private function getColumnWidth(array $namespaces): int
107+
{
108+
$widths = [];
109+
foreach ($namespaces as $name => $namespace) {
110+
$widths[] = Helper::strlen($name);
111+
foreach ($namespace['commands'] as $commandName) {
112+
$widths[] = Helper::strlen($commandName);
113+
}
114+
}
115+
116+
return $widths ? max($widths) + 2 : 0;
117+
}
118+
}

typo3/sysext/core/Classes/Command/DumpAutoloadCommand.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class DumpAutoloadCommand extends Command
3434
*/
3535
protected function configure()
3636
{
37+
$this->setName('dumpautoload');
3738
$this->setDescription('Updates class loading information in non-composer mode.');
3839
$this->setHelp('This command is only needed during development. The extension manager takes care of creating or updating this info properly during extension (de-)activation.');
3940
$this->setAliases([

typo3/sysext/core/Classes/Command/ExtensionListCommand.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ public function __construct(PackageManager $packageManager)
5050
protected function configure()
5151
{
5252
$this
53-
->setDescription('Shows the list of extensions available to the system.')
5453
->addOption(
5554
'all',
5655
'a',
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the TYPO3 CMS project.
7+
*
8+
* It is free software; you can redistribute it and/or modify it under
9+
* the terms of the GNU General Public License, either version 2
10+
* of the License, or any later version.
11+
*
12+
* For the full copyright and license information, please read the
13+
* LICENSE.txt file that was distributed with this source code.
14+
*
15+
* The TYPO3 project - inspiring people to share!
16+
*/
17+
18+
namespace TYPO3\CMS\Core\Command;
19+
20+
use Symfony\Component\Console\Command\ListCommand as SymfonyListCommand;
21+
use Symfony\Component\Console\Helper\DescriptorHelper;
22+
use Symfony\Component\Console\Input\InputInterface;
23+
use Symfony\Component\Console\Output\OutputInterface;
24+
use TYPO3\CMS\Core\Command\Descriptor\TextDescriptor;
25+
use TYPO3\CMS\Core\Console\CommandRegistry;
26+
27+
/**
28+
* ListCommand displays the list of all available commands for the application.
29+
*/
30+
class ListCommand extends SymfonyListCommand
31+
{
32+
protected CommandRegistry $commandRegistry;
33+
34+
public function __construct(CommandRegistry $commandRegistry)
35+
{
36+
$this->commandRegistry = $commandRegistry;
37+
parent::__construct();
38+
}
39+
40+
/**
41+
* {@inheritdoc}
42+
*/
43+
protected function execute(InputInterface $input, OutputInterface $output)
44+
{
45+
$helper = new DescriptorHelper();
46+
$helper->register('txt', new TextDescriptor($this->commandRegistry));
47+
$helper->describe($output, $this->getApplication(), [
48+
'format' => $input->getOption('format'),
49+
'raw_text' => $input->getOption('raw'),
50+
'namespace' => $input->getArgument('namespace'),
51+
]);
52+
53+
return 0;
54+
}
55+
}

typo3/sysext/core/Classes/Command/SendEmailCommand.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ class SendEmailCommand extends Command
4242
protected function configure()
4343
{
4444
$this
45-
->setDescription('Sends emails from the spool')
4645
->addOption('message-limit', null, InputOption::VALUE_REQUIRED, 'The maximum number of messages to send.')
4746
->addOption('time-limit', null, InputOption::VALUE_REQUIRED, 'The time limit for sending messages (in seconds).')
4847
->addOption('recover-timeout', null, InputOption::VALUE_REQUIRED, 'The timeout for recovering messages that have taken too long to send (in seconds).')

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy