-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Uid] add command to generate UIDs #36405
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
e127cb1
d9bb05a
a645108
1dab679
ea5c6a3
8c9f691
e164a17
0a024d1
8c0bf6b
e8bf438
0f02fec
78c8e2b
838f92a
c0bd623
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\Uid\Command; | ||
|
||
use Symfony\Component\Console\Command\Command; | ||
use Symfony\Component\Console\Exception\InvalidArgumentException; | ||
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\Uid\Ulid; | ||
use Symfony\Component\Uid\Uuid; | ||
|
||
class UidGenerateCommand extends Command | ||
{ | ||
protected static $defaultName = 'uid:generate'; | ||
|
||
private const UUID_1 = 'uuid-1'; | ||
private const UUID_3 = 'uuid-3'; | ||
private const UUID_4 = 'uuid-4'; | ||
private const UUID_5 = 'uuid-5'; | ||
private const UUID_6 = 'uuid-6'; | ||
private const ULID = 'ulid'; | ||
|
||
private const TYPES = [ | ||
self::UUID_1, | ||
self::UUID_3, | ||
self::UUID_4, | ||
self::UUID_5, | ||
self::UUID_6, | ||
self::ULID, | ||
]; | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected function configure() | ||
{ | ||
$typesAsString = implode(', ', self::TYPES); | ||
|
||
$this | ||
->setDefinition([ | ||
new InputArgument('type', InputArgument::REQUIRED, 'The type/version of the generated UID.'), | ||
new InputArgument('namespace', InputArgument::OPTIONAL, 'Namespace for UUID V3 and V5 versions.', ''), | ||
new InputArgument('name', InputArgument::OPTIONAL, 'Name for UUID V3 and V5 versions.', ''), | ||
new InputOption('base32', null, InputOption::VALUE_NONE, 'Use this option to represent the generated UUID/ULID in base 32.'), | ||
new InputOption('base58', null, InputOption::VALUE_NONE, 'Use this option to represent the generated UUID/ULID in base 58.'), | ||
]) | ||
->setDescription('Generates a UID, that can be either a ULID or a UUID in a given version.') | ||
->setHelp(<<<EOF | ||
The <info>%command.name%</info> generates UID. This can be a ULID or a UUID | ||
in a given version. Available types are $typesAsString. | ||
Examples: | ||
|
||
<info>php %command.full_name% ulid</info> for generating a ULID. | ||
<info>php %command.full_name% uuid-1</info> for generating a UUID in version 1. | ||
<info>php %command.full_name% uuid-3 9b7541de-6f87-11ea-ab3c-9da9a81562fc foo</info> for generating a UUID in version 3. | ||
<info>php %command.full_name% uuid-4 --base32</info> for generating a UUID in version 4 represented in base 32. | ||
|
||
EOF | ||
) | ||
; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
* | ||
* @throws \LogicException | ||
guillbdx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
*/ | ||
protected function execute(InputInterface $input, OutputInterface $output): int | ||
{ | ||
$type = $input->getArgument('type'); | ||
$namespace = $input->getArgument('namespace'); | ||
$name = $input->getArgument('name'); | ||
|
||
if (\in_array($type, [self::UUID_3, self::UUID_5], true) && !Uuid::isValid($namespace)) { | ||
throw new InvalidArgumentException('You must specify a valid namespace as a second argument.'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. worth generating/outputting one? perhaps toggle name/namespace args There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you mean that, in case the user hasn't provided a namespace, we should generate/output a random one? |
||
} | ||
|
||
switch ($type) { | ||
case self::UUID_1: | ||
$uid = Uuid::v1(); | ||
break; | ||
case self::UUID_3: | ||
$uid = Uuid::v3(Uuid::fromString($namespace), $name); | ||
break; | ||
case self::UUID_4: | ||
$uid = Uuid::v4(); | ||
break; | ||
case self::UUID_5: | ||
$uid = Uuid::v5(Uuid::fromString($namespace), $name); | ||
break; | ||
case self::UUID_6: | ||
$uid = Uuid::v6(); | ||
break; | ||
case self::ULID: | ||
$uid = new Ulid(); | ||
break; | ||
default: | ||
throw new InvalidArgumentException('Invalaible UID type. Available values are '.implode(', ', self::TYPES).'.'); | ||
guillbdx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
break; | ||
guillbdx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
if ($input->getOption('base32')) { | ||
$uid = $uid->toBase32(); | ||
} | ||
|
||
if ($input->getOption('base58')) { | ||
guillbdx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
$uid = $uid->toBase58(); | ||
} | ||
|
||
$output->writeln($uid); | ||
|
||
return 0; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
<?php | ||
|
||
|
||
namespace Symfony\Component\Uid\Tests\Command; | ||
|
||
use Symfony\Bundle\FrameworkBundle\Tests\TestCase; | ||
use Symfony\Component\Console\Application as BaseApplication; | ||
use Symfony\Component\Console\Tester\CommandTester; | ||
use Symfony\Component\Uid\Command\UidGenerateCommand; | ||
|
||
class UidGenerateCommandTest extends TestCase | ||
{ | ||
public function testGenerateUid() | ||
{ | ||
$tester = $this->getTester(); | ||
|
||
$tester->execute(['type' => 'uuid-1']); | ||
$this->assertRegExp('/[a-f\d]{8}\-[a-f\d]{4}\-1[a-f\d]{3}\-[a-f\d]{4}\-[a-f\d]{8}/i', $tester->getDisplay()); | ||
|
||
$tester->execute(['type' => 'uuid-3', 'namespace' => 'a1dc606e-741b-11ea-aa36-99e245e7882b', 'name' => 'foo']); | ||
$this->assertStringContainsString('ad4ab486-b67f-3d46-881f-21f03d27a68b', $tester->getDisplay()); | ||
|
||
$tester->execute(['type' => 'uuid-4']); | ||
$this->assertRegExp('/[a-f\d]{8}\-[a-f\d]{4}\-4[a-f\d]{3}\-[a-f\d]{4}\-[a-f\d]{8}/i', $tester->getDisplay()); | ||
|
||
$tester->execute(['type' => 'uuid-5', 'namespace' => 'a1dc606e-741b-11ea-aa36-99e245e7882b', 'name' => 'foo']); | ||
$this->assertStringContainsString('d87f160a-3cc6-520e-845f-112865bed05c', $tester->getDisplay()); | ||
|
||
$tester->execute(['type' => 'uuid-6']); | ||
$this->assertRegExp('/[a-f\d]{8}\-[a-f\d]{4}\-6[a-f\d]{3}\-[a-f\d]{4}\-[a-f\d]{8}/i', $tester->getDisplay()); | ||
|
||
$tester->execute(['type' => 'ulid']); | ||
$this->assertRegExp('/[0-9A-HJKMNP-TV-Z]{26}/i', $tester->getDisplay()); | ||
|
||
$tester->execute(['type' => 'uuid-1', '--base32' => true]); | ||
$this->assertRegExp('/[0-9A-HJKMNP-TV-Z]{26}/i', $tester->getDisplay()); | ||
|
||
$tester->execute(['type' => 'uuid-1', '--base58' => true]); | ||
$this->assertRegExp('/[1-9A-HJ-NP-Za-km-z]{22}/i', $tester->getDisplay()); | ||
} | ||
|
||
public function getTester(): CommandTester | ||
{ | ||
$application = new BaseApplication(); | ||
$application->add(new UidGenerateCommand()); | ||
$command = $application->find('uid:generate'); | ||
|
||
return new CommandTester($command); | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.