Skip to content

Commit 74267b7

Browse files
committed
[TASK] Overwrite run command
Other than what we did before we do now a full overwrite of the run command. This allows us to remove a number of less optimal constructions in the command. The change itself is empowered by the changes in phpdocumentor/guides-cli 1.9 which now provides a number of helper classes to simplify self build run commands.
1 parent 540c2aa commit 74267b7

File tree

6 files changed

+131
-81
lines changed

6 files changed

+131
-81
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"league/flysystem": "^1.1.10",
1212
"phpdocumentor/filesystem": "^1.7",
1313
"phpdocumentor/guides": "^1.7",
14-
"phpdocumentor/guides-cli": "^1.8.1",
14+
"phpdocumentor/guides-cli": "^1.9.0",
1515
"phpdocumentor/guides-graphs": "^1.0",
1616
"phpdocumentor/guides-markdown": "^1.7",
1717
"phpdocumentor/guides-restructured-text": "^1.7",

composer.lock

Lines changed: 12 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/typo3-guides-extension/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
}
1010
},
1111
"require": {
12-
"phpdocumentor/guides-cli": "^1.8.1",
12+
"phpdocumentor/guides-cli": "^1.9.0",
1313
"symfony/clock": "^6.4",
1414
"t3docs/guides-php-domain": "^1.0"
1515
}

packages/typo3-guides-extension/resources/config/typo3-guides.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@
1818
$container->services()
1919
->defaults()
2020
->autowire()
21-
->set(RunDecorator::class)
22-
->decorate(
23-
Run::class,
24-
)->args([service('.inner')])
21+
->set(Run::class, RunDecorator::class)
22+
->public()
23+
->tag('phpdoc.guides.cli.command')
2524
->set(\T3Docs\GuidesExtension\Renderer\SinglePageRenderer::class)
2625
->tag(
2726
'phpdoc.renderer.typerenderer',

packages/typo3-guides-extension/src/Command/RunDecorator.php

Lines changed: 109 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,22 @@
22

33
namespace T3Docs\GuidesExtension\Command;
44

5-
use phpDocumentor\Guides\Cli\Command\Run;
6-
use Symfony\Component\Console\Application;
5+
use League\Tactician\CommandBus;
6+
use Monolog\Handler\ErrorLogHandler;
7+
use Monolog\Handler\StreamHandler;
8+
use Monolog\Logger;
9+
use phpDocumentor\Guides\Cli\Command\ProgressBarSubscriber;
10+
use phpDocumentor\Guides\Cli\Command\SettingsBuilder;
11+
use phpDocumentor\Guides\Cli\Internal\RunCommand;
12+
use phpDocumentor\Guides\Cli\Logger\SpyProcessor;
13+
use Psr\Log\LogLevel;
714
use Symfony\Component\Console\Command\Command;
8-
use Symfony\Component\Console\Input\ArrayInput;
915
use Symfony\Component\Console\Input\InputArgument;
10-
use Symfony\Component\Console\Input\InputDefinition;
1116
use Symfony\Component\Console\Input\InputInterface;
1217
use Symfony\Component\Console\Input\InputOption;
18+
use Symfony\Component\Console\Output\ConsoleOutputInterface;
1319
use Symfony\Component\Console\Output\OutputInterface;
20+
use Symfony\Component\EventDispatcher\EventDispatcher;
1421
use Symfony\Component\Finder\Finder;
1522
use Symfony\Component\Process\Process;
1623
use T3Docs\Typo3DocsTheme\Settings\Typo3DocsInputSettings;
@@ -36,29 +43,66 @@ final class RunDecorator extends Command
3643
'README.md' => 'md',
3744
];
3845

39-
private Run $innerCommand;
40-
public function __construct(Run $innerCommand, private readonly Typo3DocsInputSettings $inputSettings)
46+
public function __construct(
47+
private readonly Typo3DocsInputSettings $inputSettings,
48+
private readonly SettingsBuilder $settingsBuilder,
49+
private readonly CommandBus $commandBus,
50+
private readonly EventDispatcher $eventDispatcher,
51+
private readonly Logger $logger,
52+
private readonly ProgressBarSubscriber $progressBarSubscriber,
53+
) {
54+
parent::__construct('run');
55+
}
56+
57+
protected function configure(): void
4158
{
42-
parent::__construct($innerCommand->getName());
43-
$this->innerCommand = $innerCommand;
59+
$this->settingsBuilder->configureCommand($this);
60+
61+
$this->addOption(
62+
'log-path',
63+
null,
64+
InputOption::VALUE_REQUIRED,
65+
'Write rendering log to this path',
66+
);
67+
$this->addOption(
68+
'fail-on-log',
69+
null,
70+
InputOption::VALUE_NONE,
71+
'If set, returns a non-zero exit code as soon as any warnings/errors occur',
72+
);
73+
74+
$this->addOption(
75+
'fail-on-error',
76+
null,
77+
InputOption::VALUE_NONE,
78+
'If set, returns a non-zero exit code as soon as any errors occur',
79+
);
4480

45-
$this->innerCommand->addOption(
81+
$this->addOption(
82+
'progress',
83+
null,
84+
InputOption::VALUE_NEGATABLE,
85+
'Whether to show a progress bar',
86+
true,
87+
);
88+
89+
$this->addOption(
4690
'localization',
4791
null,
4892
InputArgument::OPTIONAL,
4993
'Render a specific localization (for example "de_DE", "ru_RU", ...)',
5094
);
5195

5296
// This option is evaluated in the PostProjectNodeCreated event in packages/typo3-docs-theme/src/EventListeners/AddThemeSettingsToProjectNode.php
53-
$this->innerCommand->addOption(
97+
$this->addOption(
5498
'minimal-test',
5599
null,
56100
InputOption::VALUE_NONE,
57101
'Apply preset for minimal testing (format=singlepage)',
58102
);
59-
60103
}
61104

105+
62106
protected function execute(InputInterface $input, OutputInterface $output): int
63107
{
64108
$options = [];
@@ -71,25 +115,17 @@ protected function execute(InputInterface $input, OutputInterface $output): int
71115
}
72116

73117
$arguments = $input->getArguments();
118+
$guessedInput = [];
74119
if ($arguments['input'] === null) {
75120
$guessedInput = $this->guessInput(self::DEFAULT_INPUT_DIRECTORY, $output, false);
76-
} else {
77-
$guessedInput = [];
121+
$input->setArgument('input', $guessedInput['input']);
122+
$input->setOption('input-format', $guessedInput['--input-format'] ?? null);
78123
}
79124

80125
if (!isset($options['--output'])) {
81-
$options['--output'] = getcwd() . '/' . self::DEFAULT_OUTPUT_DIRECTORY;
126+
$input->setOption('output', getcwd() . '/' . self::DEFAULT_OUTPUT_DIRECTORY);
82127
}
83128

84-
$input = new ArrayInput(
85-
[
86-
...$arguments,
87-
...$options,
88-
...$guessedInput,
89-
],
90-
$this->getDefinition()
91-
);
92-
93129
// Propagate all input settings to be used within events
94130
// through the Typo3DocsInputSettings singleton.
95131
$this->inputSettings->setInput($input);
@@ -107,7 +143,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
107143
$output->writeln(sprintf("<info>DEBUG</info> Using parameters:\n%s", $readableOutput));
108144
}
109145

110-
$baseExecution = $this->innerCommand->execute($input, $output);
146+
$baseExecution = $this->internalRun($input, $output);
111147

112148
// When a localization is being rendered, no other sub-localizations
113149
// are allowed, the execution will end here.
@@ -260,48 +296,6 @@ public function retrieveLocalizationArgumentsFromCurrentArguments(InputInterface
260296
return $shellCommands;
261297
}
262298

263-
public function getDescription(): string
264-
{
265-
return $this->innerCommand->getDescription();
266-
}
267-
268-
public function getHelp(): string
269-
{
270-
return $this->innerCommand->getHelp();
271-
}
272-
273-
public function setApplication(Application $application = null): void
274-
{
275-
parent::setApplication($application);
276-
$this->innerCommand->setApplication($application);
277-
}
278-
279-
/** @return mixed[] */
280-
public function getUsages(): array
281-
{
282-
return $this->innerCommand->getUsages();
283-
}
284-
285-
public function getNativeDefinition(): InputDefinition
286-
{
287-
return $this->innerCommand->getNativeDefinition();
288-
}
289-
290-
public function getSynopsis(bool $short = false): string
291-
{
292-
return $this->innerCommand->getSynopsis($short);
293-
}
294-
295-
public function getDefinition(): InputDefinition
296-
{
297-
return $this->innerCommand->getDefinition();
298-
}
299-
300-
public function mergeApplicationDefinition(bool $mergeArgs = true): void
301-
{
302-
$this->innerCommand->mergeApplicationDefinition($mergeArgs);
303-
}
304-
305299
/** @return array<string, string> */
306300
private function guessInput(string $inputBaseDirectory, OutputInterface $output, bool $isAbsoluteDirectory = false): array
307301
{
@@ -363,4 +357,53 @@ private function guessInput(string $inputBaseDirectory, OutputInterface $output,
363357

364358
return [];
365359
}
360+
361+
private function internalRun(InputInterface $input, OutputInterface $output): int
362+
{
363+
$this->settingsBuilder->overrideWithInput($input);
364+
$projectNode = $this->settingsBuilder->createProjectNode();
365+
$settings = $this->settingsBuilder->getSettings();
366+
367+
$logPath = $settings->getLogPath();
368+
if ($logPath === 'php://stder') {
369+
$this->logger->setHandlers([new ErrorLogHandler(ErrorLogHandler::OPERATING_SYSTEM, Logger::WARNING)]);
370+
} else {
371+
$this->logger->setHandlers([new StreamHandler($logPath . '/warning.log', Logger::WARNING), new StreamHandler($logPath . '/error.log', Logger::ERROR)]);
372+
}
373+
374+
if ($settings->isFailOnError()) {
375+
$spyProcessor = new SpyProcessor($settings->getFailOnError() ?? LogLevel::WARNING);
376+
$this->logger->pushProcessor($spyProcessor);
377+
}
378+
379+
if ($output instanceof ConsoleOutputInterface && $settings->isShowProgressBar()) {
380+
$this->progressBarSubscriber->subscribe($output, $this->eventDispatcher);
381+
}
382+
383+
$documents = $this->commandBus->handle(
384+
new RunCommand($settings, $projectNode, $input),
385+
);
386+
387+
$outputFormats = $settings->getOutputFormats();
388+
$outputDir = $settings->getOutput();
389+
if ($output->isQuiet() === false) {
390+
$lastFormat = '';
391+
392+
if (count($outputFormats) > 1) {
393+
$lastFormat = (count($outputFormats) > 2 ? ',' : '') . ' and ' . strtoupper((string) array_pop($outputFormats));
394+
}
395+
396+
$formatsText = strtoupper(implode(', ', $outputFormats)) . $lastFormat;
397+
398+
$output->writeln(
399+
'Successfully placed ' . (is_countable($documents) ? count($documents) : 0) . ' rendered ' . $formatsText . ' files into ' . $outputDir,
400+
);
401+
}
402+
403+
if ($settings->isFailOnError() && $spyProcessor->hasBeenCalled()) {
404+
return Command::FAILURE;
405+
}
406+
407+
return Command::SUCCESS;
408+
}
366409
}

phpstan-baseline.neon

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ parameters:
5050
count: 1
5151
path: packages/typo3-guides-cli/src/Migration/SettingsMigrator.php
5252

53+
-
54+
message: "#^Parameter \\#1 \\$level of class phpDocumentor\\\\Guides\\\\Cli\\\\Logger\\\\SpyProcessor constructor expects 'alert'\\|'critical'\\|'debug'\\|'emergency'\\|'error'\\|'info'\\|'notice'\\|'warning'\\|null, string given\\.$#"
55+
count: 1
56+
path: packages/typo3-guides-extension/src/Command/RunDecorator.php
57+
5358
-
5459
message: "#^Cannot access offset 'packages' on mixed\\.$#"
5560
count: 1

0 commit comments

Comments
 (0)