Repository: symfony/symfony
File: src/Symfony/Bundle/SecurityBundle/Command/SecurityRoleHierarchyDumpCommand.php (PHP)

Code before:
        private readonly ?RoleHierarchyInterface $roleHierarchy = null,
    ) {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this
            ->setDefinition([
                new InputOption('direction', 'd', InputOption::VALUE_REQUIRED, 'The direction of the flowchart ['.implode('|', MermaidDumper::VALID_DIRECTIONS).']', MermaidDumper::DIRECTION_TOP_TO_BOTTOM),
                new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'The output format', 'mermaid'),
            ])
            ->setHelp(<<<'USAGE'
The <info>%command.name%</info> command dumps the role hierarchy in different formats.

<info>Mermaid</info>: %command.full_name% > roles.mmd
<info>Mermaid with direction</info>: %command.full_name% --direction=BT > roles.mmd
USAGE
            )
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        if (null === $this->roleHierarchy) {
            $output->writeln('<comment>No role hierarchy is configured.</comment>');
            return Command::SUCCESS;
        }

        $direction = $input->getOption('direction');
        $format = $input->getOption('format');

        if ('mermaid' !== $format) {
            $output->writeln('<error>Only "mermaid" format is currently supported.</error>');
            return Command::FAILURE;
        }

        if (!in_array($direction, MermaidDumper::VALID_DIRECTIONS, true)) {
            $output->writeln('<error>Invalid direction. Available options: '.implode(', ', MermaidDumper::VALID_DIRECTIONS).'</error>');
            return Command::FAILURE;
        }

        $directionMap = [
            'TB' => MermaidDumper::DIRECTION_TOP_TO_BOTTOM,
            'TD' => MermaidDumper::DIRECTION_TOP_DOWN,
            'BT' => MermaidDumper::DIRECTION_BOTTOM_TO_TOP,
            'RL' => MermaidDumper::DIRECTION_RIGHT_TO_LEFT,
            'LR' => MermaidDumper::DIRECTION_LEFT_TO_RIGHT,
        ];

        $dumper = new MermaidDumper($directionMap[$direction]);

Review comment (suggestion):
this should be written to STDERR as it is about human-readable message. this is especially important for that command which will generally send the output to a file.

When using the `SymfonyStyle` class, you have a method to access easily the error output, and you can also use the usual symfony style for command output.

Code after:
        private readonly RoleHierarchyInterface $roleHierarchy,
    ) {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this
            ->setDefinition([
                new InputOption(
                    'direction',
                    'd',
                    InputOption::VALUE_REQUIRED,
                    'The direction of the flowchart ['.implode('|', $this->getAvailableDirections()).']',
                    MermaidDirectionEnum::TOP_TO_BOTTOM->value,
                    $this->getAvailableDirections()
                ),
            ])
            ->setHelp(<<<'USAGE'
                The <info>%command.name%</info> command dumps the role hierarchy in Mermaid format.

                <info>Mermaid</info>: %command.full_name% > roles.mmd
                <info>Mermaid with direction</info>: %command.full_name% --direction=BT > roles.mmd
                USAGE
            )
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);

        if (null === $this->roleHierarchy) {
            $io->getErrorStyle()->writeln('<comment>No role hierarchy is configured.</comment>');

            return Command::SUCCESS;
        }

        $direction = $input->getOption('direction');

        if (!MermaidDirectionEnum::tryFrom($direction)) {
            $io->getErrorStyle()->writeln(\sprintf('<error>Invalid direction, available options are "%s"</error>', implode('"', $this->getAvailableDirections())));

            return Command::FAILURE;
        }

        $dumper = new MermaidDumper();
        $mermaidOutput = $dumper->dump($this->roleHierarchy, MermaidDirectionEnum::from($direction));

        $output->writeln($mermaidOutput, OutputInterface::OUTPUT_RAW);