* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Nelmio\ApiDocBundle\Command; use Nelmio\ApiDocBundle\Extractor\ApiDocExtractor; use Nelmio\ApiDocBundle\Formatter\SwaggerFormatter; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Filesystem; /** * Console command to dump Swagger-compliant API definitions. * * @author Bez Hermoso */ #[AsCommand( name: 'api:swagger:dump', description: 'Dumps Swagger-compliant API definitions.', )] class SwaggerDumpCommand extends Command { private Filesystem $filesystem; public function __construct( private readonly ApiDocExtractor $extractor, private readonly SwaggerFormatter $formatter ) { parent::__construct(); } protected function configure(): void { $this->filesystem = new Filesystem(); $this ->addOption('resource', 'r', InputOption::VALUE_OPTIONAL, 'A specific resource API declaration to dump.') ->addOption('list-only', 'l', InputOption::VALUE_NONE, 'Dump resource list only.') ->addOption('pretty', 'p', InputOption::VALUE_NONE, 'Dump as prettified JSON.') ->addArgument('destination', InputArgument::OPTIONAL, 'Directory to dump JSON files in.', null) ; } protected function execute(InputInterface $input, OutputInterface $output): int { if ($input->getOption('list-only') && $input->getOption('resource')) { throw new \RuntimeException('Cannot selectively dump a resource with the --list-only flag.'); } $apiDocs = $this->extractor->all(); if ($input->getOption('list-only')) { $data = $this->getResourceList($apiDocs); $this->dump($data, null, $input, $output); return 0; } if (false !== ($resource = $input->getOption('resource'))) { $data = $this->getApiDeclaration($apiDocs, $resource); if (count($data['apis']) === 0) { throw new \InvalidArgumentException(sprintf('Resource "%s" does not exist.', $resource)); } $this->dump($data, $resource, $input, $output); return 0; } /* * If --list-only and --resource is not specified, dump everything. */ $data = $this->getResourceList($apiDocs); if (!$input->getArguments('destination')) { $output->writeln(''); $output->writeln('Resource list: '); } $this->dump($data, null, $input, $output, false); foreach ($data['apis'] as $api) { $resource = substr($api['path'], 1); if (!$input->getArgument('destination')) { $output->writeln(''); $output->writeln(sprintf('API declaration for "%s" resource: ', $resource)); } $data = $this->getApiDeclaration($apiDocs, $resource, $output); $this->dump($data, $resource, $input, $output, false); } return 0; } protected function dump(array $data, $resource, InputInterface $input, OutputInterface $output, $treatAsFile = true): void { $destination = $input->getArgument('destination'); $content = json_encode($data, $input->getOption('pretty') ? JSON_PRETTY_PRINT : 0); if (!$destination) { $output->writeln($content); return; } if ($treatAsFile === false) { if (!$this->filesystem->exists($destination)) { $this->filesystem->mkdir($destination); } } if (!$resource) { if (!$treatAsFile) { $destination = sprintf('%s/api-docs.json', rtrim($destination, '\\/')); } $message = sprintf('Dumping resource list to %s: ', $destination); $this->writeToFile($content, $destination, $output, $message); return; } if ($treatAsFile === false) { $destination = sprintf('%s/%s.json', rtrim($destination, '\\/'), $resource); } $message = sprintf('Dump API declaration to %s: ', $destination); $this->writeToFile($content, $destination, $output, $message); } protected function writeToFile($content, $file, OutputInterface $output, $message): void { try { $this->filesystem->dumpFile($file, $content); $message .= ' OK'; } catch (IOException $e) { $message .= sprintf(' NOT OK - %s', $e->getMessage()); } $output->writeln($message); } protected function getResourceList(array $data) { return $this->formatter->format($data); } protected function getApiDeclaration(array $data, $resource) { return $this->formatter->format($data, '/' . $resource); } }