8000 [Uid] Add Generate and Inspect commands · symfony/symfony@ba8a28b · GitHub
[go: up one dir, main page]

Skip to content

Commit ba8a28b

Browse files
[Uid] Add Generate and Inspect commands
Co-authored-by: Nicolas Grekas <nicolas.grekas@gmail.com>
1 parent bc9e946 commit ba8a28b

12 files changed

+1056
-8
lines changed

src/Symfony/Component/Serializer/Normalizer/UidNormalizer.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ final class UidNormalizer implements NormalizerInterface, DenormalizerInterface,
2222
public const NORMALIZATION_FORMAT_KEY = 'uid_normalization_format';
2323

2424
public const NORMALIZATION_FORMAT_CANONICAL = 'canonical';
25-
public const NORMALIZATION_FORMAT_BASE_58 = 'base_58';
26-
public const NORMALIZATION_FORMAT_BASE_32 = 'base_32';
27-
public const NORMALIZATION_FORMAT_RFC_4122 = 'rfc_4122';
25+
public const NORMALIZATION_FORMAT_BASE58 = 'base58';
26+
public const NORMALIZATION_FORMAT_BASE32 = 'base32';
27+
public const NORMALIZATION_FORMAT_RFC4122 = 'rfc4122';
2828

2929
private $defaultContext = [
3030
self::NORMALIZATION_FORMAT_KEY => self::NORMALIZATION_FORMAT_CANONICAL,
@@ -45,11 +45,11 @@ public function normalize($object, string $format = null, array $context = [])
4545
switch ($context[self::NORMALIZATION_FORMAT_KEY] ?? $this->defaultContext[self::NORMALIZATION_FORMAT_KEY]) {
4646
case self::NORMALIZATION_FORMAT_CANONICAL:
4747
return (string) $object;
48-
case self::NORMALIZATION_FORMAT_BASE_58:
48+
case self::NORMALIZATION_FORMAT_BASE58:
4949
return $object->toBase58();
50-
case self::NORMALIZATION_FORMAT_BASE_32:
50+
case self::NORMALIZATION_FORMAT_BASE32:
5151
return $object->toBase32();
52-
case self::NORMALIZATION_FORMAT_RFC_4122:
52+
case self::NORMALIZATION_FORMAT_RFC4122:
5353
return $object->toRfc4122();
5454
}
5555

src/Symfony/Component/Serializer/Tests/Normalizer/UidNormalizerTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function testSupportsNormalization()
3939

4040
public function normalizeProvider()
4141
{
42-
$uidFormats = [null, 'canonical', 'base_58', 'base_32', 'rfc_4122'];
42+
$uidFormats = [null, 'canonical', 'base58', 'base32', 'rfc4122'];
4343
$data = [
4444
[
4545
UuidV1::fromString('9b7541de-6f87-11ea-ab3c-9da9a81562fc'),
@@ -149,7 +149,7 @@ public function testDenormalize($uuidString, $class)
149149
public function testNormalizeWithNormalizationFormatPassedInConstructor()
150150
{
151151
$uidNormalizer = new UidNormalizer([
152-
'uid_normalization_format' => 'rfc_4122',
152+
'uid_normalization_format' => 'rfc4122',
153153
]);
154154
$ulid = Ulid::fromString('01ETWV01C0GYQ5N92ZK7QRGB10');
155155

src/Symfony/Component/Uid/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ CHANGELOG
99
* [BC BREAK] Replace `UuidV1::getTime()`, `UuidV6::getTime()` and `Ulid::getTime()` by `UuidV1::getDateTime()`, `UuidV6::getDateTime()` and `Ulid::getDateTime()`
1010
* Add `Uuid::NAMESPACE_*` constants from RFC4122
1111
* Add `UlidFactory`, `UuidFactory`, `RandomBasedUuidFactory`, `TimeBasedUuidFactory` and `NameBasedUuidFactory`
12+
* Add commands to generate and inspect UUIDs and ULIDs
1213

1314
5.2.0
1415
-----
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Uid\Command;
13+
14+
use Symfony\Component\Console\Command\Command;
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\UlidFactory;
21+
use Symfony\Component\Uid\Ulid;
22+
23+
class GenerateUlidCommand extends Command
24+
{
25+
protected static $defaultName = 'ulid:generate';
26+
protected static $defaultDescription = 'Generates a ULID';
27+
28+
private $factory;
29+
30+
public function __construct(UlidFactory $factory = null)
31+
{
32+
$this->factory = $factory ?? new UlidFactory();
33+
34+
parent::__construct();
35+
}
36+
37+
/**
38+
* {@inheritdoc}
39+
*/
40+
protected function configure(): void
41+
{
42+
$this
43+
->setDefinition([
44+
new InputOption('time', null, InputOption::VALUE_REQUIRED, 'The ULID timestamp: a parsable date/time string'),
45+
new InputOption('count', 'c', InputOption::VALUE_REQUIRED, 'The number of ULID to generate', 1),
46+
new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'The ULID output format: base32, base58 or rfc4122', 'base32'),
47+
])
48+
->setDescription(self::$defaultDescription)
49+
->setHelp(<<<'EOF'
50+
The <info>%command.name%</info> command generates a ULID.
51+
52+
<info>php %command.full_name%</info>
53+
54+
To specify the timestamp:
55+
56+
<info>php %command.full_name% --time="2021-02-16 14:09:08"</info>
57+
58+
To generate several ULIDs:
59+
60+
<info>php %command.full_name% --count=10</info>
61+
62+
To output a specific format:
63+
64+
<info>php %command.full_name% --format=rfc4122</info>
65+
EOF
66+
)
67+
;
68+
}
69+
70+
/**
71+
* {@inheritdoc}
72+
*/
73+
protected function execute(InputInterface $input, OutputInterface $output)
74+
{
75+
$io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output);
76+
77+
if (null !== $time = $input->getOption('time')) {
78+
try {
79+
$time = new \DateTimeImmutable($time);
80+
} catch (\Exception $e) {
81+
$io->error(sprintf('Invalid timestamp "%s": %s', $time, str_replace('DateTimeImmutable::__construct(): ', '', $e->getMessage())));
82+
83+
return 1;
84+
}
85+
}
86+
87+
switch ($input->getOption('format')) {
88+
case 'base32': $format = 'toBase32'; break;
89+
case 'base58': $format = 'toBase58'; break;
90+
case 'rfc4122': $format = 'toRfc4122'; break;
91+
92+
default:
93+
$io->error(sprintf('Invalid format "%s", did you mean "base32", "base58" or "rfc4122"?', $input->getOption('format')));
94+
95+
return 1;
96+
}
97+
98+
$count = (int) $input->getOption('count');
99+
try {
100+
for ($i = 0; $i < $count; ++$i) {
101+
$output->writeln($this->factory->create($time)->$format());
102+
}
103+
} catch (\Exception $e) {
104+
$io->error($e->getMessage());
105+
106+
return 1;
107+
}
108+
109+
return 0;
110+
}
111+
}
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Uid\Command;
13+
14+
use Symfony\Component\Console\Command\Command;
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+
23+
class GenerateUuidCommand extends Command
24+
{
25+
protected static $defaultName = 'uuid:generate';
26+
protected static $defaultDescription = 'Generates a UUID';
27+
28+
private $factory;
29+
30+
public function __construct(UuidFactory $factory = null)
31+
{
32+
$this->factory = $factory ?? new UuidFactory();
33+
34+
parent::__construct();
35+
}
36+
37+
/**
38+
* {@inheritdoc}
39+
*/
40+
protected function configure(): void
41+
{
42+
$this
43+
->setDefinition([
44+
new InputOption('time-based', null, InputOption::VALUE_REQUIRED, 'The timestamp, to generate a time-based UUID: a parsable date/time string'),
45+
new InputOption('node', null, InputOption::VALUE_REQUIRED, 'The UUID whose node part should be used as the node of the generated UUID'),
46+
new InputOption('name-based', null, InputOption::VALUE_REQUIRED, 'The name, to generate a name-based UUID'),
47+
new InputOption('namespace', null, InputOption::VALUE_REQUIRED, 'The UUID to use at the namespace for named-based UUIDs'),
48+
new InputOption('random-based', null, InputOption::VALUE_NONE, 'To generate a random-based UUID'),
49+
new InputOption('count', 'c', InputOption::VALUE_REQUIRED, 'The number of UUID to generate', 1),
50+
new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'The UUID output format: rfc4122, base58 or base32', 'rfc4122'),
51+
])
52+
->setDescription(self::$defaultDescription)
53+
->setHelp(<<<'EOF'
54+
The <info>%command.name%</info> generates a UUID.
55+
56+
<info>php %command.full_name%</info>
57+
58+
To generate a time-based UUID:
59+
60+
<info>php %command.full_name% --time-based=now</info>
61+
62+
To specify a time-based UUID's node:
63+
64+
<info>php %command.full_name% --time-based=@1613480254 --node=fb3502dc-137e-4849-8886-ac90d07f64a7</info>
65+
66+
To generate a name-based UUID:
67+
68+
<info>php %command.full_name% --name-based=foo</info>
69+
70+
To specify a name-based UUID's namespace:
71+
72+
<info>php %command.full_name% --name-based=bar --namespace=fb3502dc-137e-4849-8886-ac90d07f64a7</info>
73+
74+
To generate a random-based UUID:
75+
76+
<info>php %command.full_name% --random-based</info>
77+
78+
To generate several UUIDs:
79+
80+
<info>php %command.full_name% --count=10</info>
81+
82+
To output a specific format:
83+
84+
<info>php %command.full_name% --format=base58</info>
85+
EOF
86+
)
87+
;
88+
}
89+
90+
/**
91+
* {@inheritdoc}
92+
*/
93+
protected function execute(InputInterface $input, OutputInterface $output)
94+
{
95+
$io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output);
96+
97+
$time = $input->getOption('time-based');
98+
$node = $input->getOption('node');
99+
$name = $input->getOption('name-based');
100+
$namespace = $input->getOption('namespace');
101+
$random = $input->getOption('random-based');
102+
103+
if (false !== ($time ?? $name ?? $random) && 1 < ((null !== $time) + (null !== $name) + $random)) {
104+
$io->error('Only one of "--time-based", "--name-based" or "--random-based" can be provided at a time.');
105+
106+
return 1;
107+
}
108+
109+
if (null === $time && null !== $node) {
110+
$io->error('Option "--node" can only be used with "--time-based".');
111+
112+
return 1;
113+
}
114+
115+
if (null === $name && null !== $namespace) {
116+
$io->error('Option "--namespace" can only be used with "--name-based".');
117+
118+
return 1;
119+
}
120+
121+
switch (true) {
122+
case null !== $time:
123+
if (null !== $node) {
124+
try {
125+
$node = Uuid::fromString($node);
126+
} catch (\InvalidArgumentException $e) {
127+
$io->error(sprintf('Invalid node "%s": %s', $node, $e->getMessage()));
128+
129+
return 1;
130+
}
131+
}
132+
133+
try {
134+
$time = new \DateTimeImmutable($time);
135+
} catch (\Exception $e) {
136+
$io->error(sprintf('Invalid timestamp "%s": %s', $time, str_replace('DateTimeImmutable::__construct(): ', '', $e->getMessage())));
137+
138+
return 1;
139+
}
140+
141+
$create = function () use ($node, $time): Uuid {
142+
return $this->factory->timeBased($node)->create($time);
143+
};
144+
break;
145+
146+
case null !== $name:
147+
if ($namespace) {
148+
try {
149+
$namespace = Uuid::fromString($namespace);
150+
} catch (\InvalidArgumentException $e) {
151+
$io->error(sprintf('Invalid namespace "%s": %s', $namespace, $e->getMessage()));
152+
153+
return 1;
154+
}
155+
}
156+
157+
$create = function () use ($namespace, $name, $io): Uuid {
158+
try {
159+
$factory = $this->factory->nameBased($namespace);
160+
} catch (\LogicException $e) {
161+
throw new \InvalidArgumentException('Missing namespace: use the "--namespace" option or configure a default namespace in the underlying factory.');
162+
}
163+
164+
return $factory->create($name);
165+
};
166+
break;
167+
168+
case false !== $random:
169+
$create = [$this->factory->randomBased(), 'create'];
170+
break;
171+
172+
default:
173+
$create = [$this->factory, 'create'];
174+
break;
175+
}
176+
177+
switch ($input->getOption('format')) {
178+
case 'base32': $format = 'toBase32'; break;
179+
case 'base58': $format = 'toBase58'; break;
180+
case 'rfc4122': $format = 'toRfc4122'; break;
181+
182+
default:
183+
$io->error(sprintf('Invalid format "%s", did you mean "base32", "base58" or "rfc4122"?', $input->getOption('format')));
184+
185+
return 1;
186+
}
187+
188+
$count = (int) $input->getOption('count');
189+
try {
190+
for ($i = 0; $i < $count; ++$i) {
191+
$output->writeln($create()->$format());
192+
}
193+
} catch (\Exception $e) {
194+
$io->error($e->getMessage());
195+
196+
return 1;
197+
}
198+
199+
return 0;
200+
}
201+
}

0 commit comments

Comments
 (0)
0