vendor/symfony/uid/Command/GenerateUuidCommand.php line 31

  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\Uid\Command;
  11. use Symfony\Component\Console\Attribute\AsCommand;
  12. use Symfony\Component\Console\Command\Command;
  13. use Symfony\Component\Console\Completion\CompletionInput;
  14. use Symfony\Component\Console\Completion\CompletionSuggestions;
  15. use Symfony\Component\Console\Input\InputInterface;
  16. use Symfony\Component\Console\Input\InputOption;
  17. use Symfony\Component\Console\Output\ConsoleOutputInterface;
  18. use Symfony\Component\Console\Output\OutputInterface;
  19. use Symfony\Component\Console\Style\SymfonyStyle;
  20. use Symfony\Component\Uid\Factory\UuidFactory;
  21. use Symfony\Component\Uid\Uuid;
  22. #[AsCommand(name'uuid:generate'description'Generate a UUID')]
  23. class GenerateUuidCommand extends Command
  24. {
  25.     private UuidFactory $factory;
  26.     public function __construct(UuidFactory $factory null)
  27.     {
  28.         $this->factory $factory ?? new UuidFactory();
  29.         parent::__construct();
  30.     }
  31.     protected function configure(): void
  32.     {
  33.         $this
  34.             ->setDefinition([
  35.                 new InputOption('time-based'nullInputOption::VALUE_REQUIRED'The timestamp, to generate a time-based UUID: a parsable date/time string'),
  36.                 new InputOption('node'nullInputOption::VALUE_REQUIRED'The UUID whose node part should be used as the node of the generated UUID'),
  37.                 new InputOption('name-based'nullInputOption::VALUE_REQUIRED'The name, to generate a name-based UUID'),
  38.                 new InputOption('namespace'nullInputOption::VALUE_REQUIRED'The UUID to use at the namespace for named-based UUIDs, predefined namespaces keywords "dns", "url", "oid" and "x500" are accepted'),
  39.                 new InputOption('random-based'nullInputOption::VALUE_NONE'To generate a random-based UUID'),
  40.                 new InputOption('count''c'InputOption::VALUE_REQUIRED'The number of UUID to generate'1),
  41.                 new InputOption('format''f'InputOption::VALUE_REQUIRED'The UUID output format: rfc4122, base58 or base32''rfc4122'),
  42.             ])
  43.             ->setHelp(<<<'EOF'
  44. The <info>%command.name%</info> generates a UUID.
  45.     <info>php %command.full_name%</info>
  46. To generate a time-based UUID:
  47.     <info>php %command.full_name% --time-based=now</info>
  48. To specify a time-based UUID's node:
  49.     <info>php %command.full_name% --time-based=@1613480254 --node=fb3502dc-137e-4849-8886-ac90d07f64a7</info>
  50. To generate a name-based UUID:
  51.     <info>php %command.full_name% --name-based=foo</info>
  52. To specify a name-based UUID's namespace:
  53.     <info>php %command.full_name% --name-based=bar --namespace=fb3502dc-137e-4849-8886-ac90d07f64a7</info>
  54. To generate a random-based UUID:
  55.     <info>php %command.full_name% --random-based</info>
  56. To generate several UUIDs:
  57.     <info>php %command.full_name% --count=10</info>
  58. To output a specific format:
  59.     <info>php %command.full_name% --format=base58</info>
  60. EOF
  61.             )
  62.         ;
  63.     }
  64.     protected function execute(InputInterface $inputOutputInterface $output): int
  65.     {
  66.         $io = new SymfonyStyle($input$output instanceof ConsoleOutputInterface $output->getErrorOutput() : $output);
  67.         $time $input->getOption('time-based');
  68.         $node $input->getOption('node');
  69.         $name $input->getOption('name-based');
  70.         $namespace $input->getOption('namespace');
  71.         $random $input->getOption('random-based');
  72.         if (false !== ($time ?? $name ?? $random) && < ((null !== $time) + (null !== $name) + $random)) {
  73.             $io->error('Only one of "--time-based", "--name-based" or "--random-based" can be provided at a time.');
  74.             return 1;
  75.         }
  76.         if (null === $time && null !== $node) {
  77.             $io->error('Option "--node" can only be used with "--time-based".');
  78.             return 1;
  79.         }
  80.         if (null === $name && null !== $namespace) {
  81.             $io->error('Option "--namespace" can only be used with "--name-based".');
  82.             return 1;
  83.         }
  84.         switch (true) {
  85.             case null !== $time:
  86.                 if (null !== $node) {
  87.                     try {
  88.                         $node Uuid::fromString($node);
  89.                     } catch (\InvalidArgumentException $e) {
  90.                         $io->error(sprintf('Invalid node "%s": %s'$node$e->getMessage()));
  91.                         return 1;
  92.                     }
  93.                 }
  94.                 try {
  95.                     new \DateTimeImmutable($time);
  96.                 } catch (\Exception $e) {
  97.                     $io->error(sprintf('Invalid timestamp "%s": %s'$timestr_replace('DateTimeImmutable::__construct(): '''$e->getMessage())));
  98.                     return 1;
  99.                 }
  100.                 $create = function () use ($node$time): Uuid {
  101.                     return $this->factory->timeBased($node)->create(new \DateTimeImmutable($time));
  102.                 };
  103.                 break;
  104.             case null !== $name:
  105.                 if ($namespace && !\in_array($namespace, ['dns''url''oid''x500'], true)) {
  106.                     try {
  107.                         $namespace Uuid::fromString($namespace);
  108.                     } catch (\InvalidArgumentException $e) {
  109.                         $io->error(sprintf('Invalid namespace "%s": %s'$namespace$e->getMessage()));
  110.                         return 1;
  111.                     }
  112.                 }
  113.                 $create = function () use ($namespace$name): Uuid {
  114.                     try {
  115.                         $factory $this->factory->nameBased($namespace);
  116.                     } catch (\LogicException) {
  117.                         throw new \InvalidArgumentException('Missing namespace: use the "--namespace" option or configure a default namespace in the underlying factory.');
  118.                     }
  119.                     return $factory->create($name);
  120.                 };
  121.                 break;
  122.             case $random:
  123.                 $create $this->factory->randomBased()->create(...);
  124.                 break;
  125.             default:
  126.                 $create $this->factory->create(...);
  127.                 break;
  128.         }
  129.         $formatOption $input->getOption('format');
  130.         if (\in_array($formatOption$this->getAvailableFormatOptions())) {
  131.             $format 'to'.ucfirst($formatOption);
  132.         } else {
  133.             $io->error(sprintf('Invalid format "%s", did you mean "base32", "base58" or "rfc4122"?'$formatOption));
  134.             return 1;
  135.         }
  136.         $count = (int) $input->getOption('count');
  137.         try {
  138.             for ($i 0$i $count; ++$i) {
  139.                 $output->writeln($create()->$format());
  140.             }
  141.         } catch (\Exception $e) {
  142.             $io->error($e->getMessage());
  143.             return 1;
  144.         }
  145.         return 0;
  146.     }
  147.     public function complete(CompletionInput $inputCompletionSuggestions $suggestions): void
  148.     {
  149.         if ($input->mustSuggestOptionValuesFor('format')) {
  150.             $suggestions->suggestValues($this->getAvailableFormatOptions());
  151.         }
  152.     }
  153.     private function getAvailableFormatOptions(): array
  154.     {
  155.         return [
  156.             'base32',
  157.             'base58',
  158.             'rfc4122',
  159.         ];
  160.     }
  161. }