diff --git a/packages/guides-cli/src/Command/Run.php b/packages/guides-cli/src/Command/Run.php index 7c65b3c23..d1834038a 100644 --- a/packages/guides-cli/src/Command/Run.php +++ b/packages/guides-cli/src/Command/Run.php @@ -13,7 +13,14 @@ use Monolog\Logger; use phpDocumentor\Guides\Cli\Logger\SpyProcessor; use phpDocumentor\Guides\Compiler\CompilerContext; +use phpDocumentor\Guides\Event\PostCollectFilesForParsingEvent; +use phpDocumentor\Guides\Event\PostParseDocument; +use phpDocumentor\Guides\Event\PostParseProcess; use phpDocumentor\Guides\Event\PostRenderDocument; +use phpDocumentor\Guides\Event\PostRenderProcess; +use phpDocumentor\Guides\Event\PreParseDocument; +use phpDocumentor\Guides\Event\PreRenderDocument; +use phpDocumentor\Guides\Event\PreRenderProcess; use phpDocumentor\Guides\Handlers\CompileDocumentsCommand; use phpDocumentor\Guides\Handlers\ParseDirectoryCommand; use phpDocumentor\Guides\Handlers\ParseFileCommand; @@ -39,6 +46,7 @@ use function implode; use function is_countable; use function is_dir; +use function microtime; use function pathinfo; use function realpath; use function sprintf; @@ -117,6 +125,80 @@ public function __construct( ); } + public function registerProgressBar(ConsoleOutputInterface $output): void + { + $parsingProgressBar = new ProgressBar($output->section()); + $parsingProgressBar->setFormat('Parsing: %current%/%max% [%bar%] %percent:3s%% %message%'); + $parsingStartTime = microtime(true); + $this->eventDispatcher->addListener( + PostCollectFilesForParsingEvent::class, + static function (PostCollectFilesForParsingEvent $event) use ($parsingProgressBar, &$parsingStartTime): void { + // Each File needs to be first parsed then rendered + $parsingStartTime = microtime(true); + $parsingProgressBar->setMaxSteps(count($event->getFiles())); + }, + ); + $this->eventDispatcher->addListener( + PreParseDocument::class, + static function (PreParseDocument $event) use ($parsingProgressBar): void { + $parsingProgressBar->setMessage('Parsing file: ' . $event->getFileName()); + $parsingProgressBar->display(); + }, + ); + $this->eventDispatcher->addListener( + PostParseDocument::class, + static function (PostParseDocument $event) use ($parsingProgressBar): void { + $parsingProgressBar->advance(); + }, + ); + $this->eventDispatcher->addListener( + PostParseProcess::class, + static function (PostParseProcess $event) use ($parsingProgressBar, $parsingStartTime): void { + $parsingTimeElapsed = microtime(true) - $parsingStartTime; + $parsingProgressBar->setMessage(sprintf( + 'Parsed %s files in %.2f seconds', + $parsingProgressBar->getMaxSteps(), + $parsingTimeElapsed, + )); + $parsingProgressBar->finish(); + }, + ); + $that = $this; + $this->eventDispatcher->addListener( + PreRenderProcess::class, + static function (PreRenderProcess $event) use ($that, $output): void { + $renderingProgressBar = new ProgressBar($output->section(), count($event->getCommand()->getDocumentArray())); + $renderingProgressBar->setFormat('Rendering: %current%/%max% [%bar%] %percent:3s%% Output format ' . $event->getCommand()->getOutputFormat() . ': %message%'); + $renderingStartTime = microtime(true); + $that->eventDispatcher->addListener( + PreRenderDocument::class, + static function (PreRenderDocument $event) use ($renderingProgressBar): void { + $renderingProgressBar->setMessage('Rendering: ' . $event->getCommand()->getFileDestination()); + $renderingProgressBar->display(); + }, + ); + $that->eventDispatcher->addListener( + PostRenderDocument::class, + static function (PostRenderDocument $event) use ($renderingProgressBar): void { + $renderingProgressBar->advance(); + }, + ); + $that->eventDispatcher->addListener( + PostRenderProcess::class, + static function (PostRenderProcess $event) use ($renderingProgressBar, $renderingStartTime): void { + $renderingElapsedTime = microtime(true) - $renderingStartTime; + $renderingProgressBar->setMessage(sprintf( + 'Rendered %s documents in %.2f seconds', + $renderingProgressBar->getMaxSteps(), + $renderingElapsedTime, + )); + $renderingProgressBar->finish(); + }, + ); + }, + ); + } + private function getSettingsOverridenWithInput(InputInterface $input): ProjectSettings { $settings = $this->settingsManager->getProjectSettings(); @@ -200,6 +282,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int $documents = []; + + if ($output instanceof ConsoleOutputInterface && $settings->isShowProgressBar()) { + $this->registerProgressBar($output); + } + if ($settings->getInputFile() === '') { $documents = $this->commandBus->handle( new ParseDirectoryCommand( @@ -231,16 +318,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $outputFormats = $settings->getOutputFormats(); - if ($output instanceof ConsoleOutputInterface && $settings->isShowProgressBar()) { - $progressBar = new ProgressBar($output->section(), count($documents)); - $this->eventDispatcher->addListener( - PostRenderDocument::class, - static function (PostRenderDocument $event) use ($progressBar): void { - $progressBar->advance(); - }, - ); - } - foreach ($outputFormats as $format) { $this->commandBus->handle( new RenderCommand( diff --git a/packages/guides/src/Event/PostCollectFilesForParsingEvent.php b/packages/guides/src/Event/PostCollectFilesForParsingEvent.php new file mode 100644 index 000000000..234a6ae44 --- /dev/null +++ b/packages/guides/src/Event/PostCollectFilesForParsingEvent.php @@ -0,0 +1,38 @@ +command; + } + + public function getFiles(): Files + { + return $this->files; + } + + public function setFiles(Files $files): void + { + $this->files = $files; + } +} diff --git a/packages/guides/src/Event/PostRenderDocument.php b/packages/guides/src/Event/PostRenderDocument.php index d79c3f435..771c2cab2 100644 --- a/packages/guides/src/Event/PostRenderDocument.php +++ b/packages/guides/src/Event/PostRenderDocument.php @@ -16,8 +16,10 @@ final class PostRenderDocument { /** @param NodeRenderer $renderer */ - public function __construct(private readonly NodeRenderer $renderer, private readonly RenderDocumentCommand $command) - { + public function __construct( + private readonly NodeRenderer $renderer, + private readonly RenderDocumentCommand $command, + ) { } /** @return NodeRenderer */ diff --git a/packages/guides/src/Event/PreRenderProcess.php b/packages/guides/src/Event/PreRenderProcess.php index ec2c46d52..75d6a301f 100644 --- a/packages/guides/src/Event/PreRenderProcess.php +++ b/packages/guides/src/Event/PreRenderProcess.php @@ -17,8 +17,10 @@ final class PreRenderProcess { private bool $exitRendering = false; - public function __construct(private readonly RenderCommand $command) - { + public function __construct( + private readonly RenderCommand $command, + private readonly int $steps = 1, + ) { } public function getCommand(): RenderCommand @@ -37,4 +39,9 @@ public function setExitRendering(bool $exitRendering): PreRenderProcess return $this; } + + public function getSteps(): int + { + return $this->steps; + } } diff --git a/packages/guides/src/Files.php b/packages/guides/src/Files.php index a55845050..47a77cd88 100644 --- a/packages/guides/src/Files.php +++ b/packages/guides/src/Files.php @@ -14,13 +14,15 @@ namespace phpDocumentor\Guides; use ArrayIterator; +use Countable; use Iterator; use IteratorAggregate; +use function count; use function in_array; /** @implements IteratorAggregate */ -final class Files implements IteratorAggregate +final class Files implements IteratorAggregate, Countable { /** @var string[] */ private array $files = []; @@ -39,4 +41,9 @@ public function getIterator(): Iterator { return new ArrayIterator($this->files); } + + public function count(): int + { + return count($this->files); + } } diff --git a/packages/guides/src/Handlers/ParseDirectoryHandler.php b/packages/guides/src/Handlers/ParseDirectoryHandler.php index 762fe84fa..9be61fbba 100644 --- a/packages/guides/src/Handlers/ParseDirectoryHandler.php +++ b/packages/guides/src/Handlers/ParseDirectoryHandler.php @@ -7,6 +7,7 @@ use InvalidArgumentException; use League\Flysystem\FilesystemInterface; use League\Tactician\CommandBus; +use phpDocumentor\Guides\Event\PostCollectFilesForParsingEvent; use phpDocumentor\Guides\Event\PostParseProcess; use phpDocumentor\Guides\Event\PreParseProcess; use phpDocumentor\Guides\FileCollector; @@ -47,18 +48,23 @@ public function handle(ParseDirectoryCommand $command): array ); $files = $this->fileCollector->collect($origin, $currentDirectory, $extension); + + $postCollectFilesForParsingEvent = $this->eventDispatcher->dispatch( + new PostCollectFilesForParsingEvent($command, $files), + ); + assert($postCollectFilesForParsingEvent instanceof PostCollectFilesForParsingEvent); /** @var DocumentNode[] $documents */ $documents = []; - foreach ($files as $file) { + foreach ($postCollectFilesForParsingEvent->getFiles() as $file) { $documents[] = $this->commandBus->handle( new ParseFileCommand($origin, $currentDirectory, $file, $extension, 1, $command->getProjectNode(), $indexName === $file), ); } - $postParseProcessEvent = $this->eventDispatcher->dispatch( + $postCollectFilesForParsingEvent = $this->eventDispatcher->dispatch( new PostParseProcess($command, $documents), ); - assert($postParseProcessEvent instanceof PostParseProcess); + assert($postCollectFilesForParsingEvent instanceof PostParseProcess); return $documents; } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 99d5552b3..43ad8a69c 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -32,7 +32,7 @@ parameters: - message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, mixed given\\.$#" - count: 2 + count: 1 path: packages/guides-cli/src/Command/Run.php -