Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 88a99dd

Browse filesBrowse files
fancywebnicolas-grekas
authored andcommitted
[Uid] Add UuidFactory to create Ulid and Uuid from timestamps, namespaces and nodes
1 parent 37e1823 commit 88a99dd
Copy full SHA for 88a99dd

23 files changed

+833
-27
lines changed

‎src/Symfony/Bridge/Doctrine/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ CHANGELOG
66

77
* Deprecate `DoctrineTestHelper` and `TestRepositoryFactory`
88
* [BC BREAK] Remove `UuidV*Generator` classes
9+
* Add `UuidGenerator`
910

1011
5.2.0
1112
-----

‎src/Symfony/Bridge/Doctrine/IdGenerator/UlidGenerator.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/IdGenerator/UlidGenerator.php
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,24 @@
1313

1414
use Doctrine\ORM\EntityManager;
1515
use Doctrine\ORM\Id\AbstractIdGenerator;
16+
use Symfony\Component\Uid\Factory\UlidFactory;
1617
use Symfony\Component\Uid\Ulid;
1718

1819
final class UlidGenerator extends AbstractIdGenerator
1920
{
21+
private $factory;
22+
23+
public function __construct(UlidFactory $factory = null)
24+
{
25+
$this->factory = $factory;
26+
}
27+
2028
public function generate(EntityManager $em, $entity): Ulid
2129
{
30+
if ($this->factory) {
31+
return $this->factory->create();
32+
}
33+
2234
return new Ulid();
2335
}
2436
}
+82Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
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\Bridge\Doctrine\IdGenerator;
13+
14+
use Doctrine\ORM\EntityManager;
15+
use Doctrine\ORM\Id\AbstractIdGenerator;
16+
use Symfony\Component\Uid\Factory\UuidFactory;
17+
use Symfony\Component\Uid\Uuid;
18+
19+
final class UuidGenerator extends AbstractIdGenerator
20+
{
21+
private $protoFactory;
22+
private $factory;
23+
private $entityGetter;
24+
25+
public function __construct(UuidFactory $factory = null)
26+
{
27+
$this->protoFactory = $this->factory = $factory ?? new UuidFactory();
28+
}
29+
30+
public function generate(EntityManager $em, $entity): Uuid
31+
{
32+
if (null !== $this->entityGetter) {
33+
if (\is_callable([$entity, $this->entityGetter])) {
34+
return $this->factory->create($entity->{$this->entityGetter}());
35+
}
36+
37+
return $this->factory->create($entity->{$this->entityGetter});
38+
}
39+
40+
return $this->factory->create();
41+
}
42+
43+
/**
44+
* @param Uuid|string|null $namespace
45+
*
46+
* @return static
47+
*/
48+
public function nameBased(string $entityGetter, $namespace = null): self
49+
{
50+
$clone = clone $this;
51+
$clone->factory = $clone->protoFactory->nameBased($namespace);
52+
$clone->entityGetter = $entityGetter;
53+
54+
return $clone;
55+
}
56+
57+
/**
58+
* @return static
59+
*/
60+
public function randomBased(): self
61+
{
62+
$clone = clone $this;
63+
$clone->factory = $clone->protoFactory->randomBased();
64+
$clone->entityGetter = null;
65+
66+
return $clone;
67+
}
68+
69+
/**
70+
* @param Uuid|string|null $node
71+
*
72+
* @return static
73+
*/
74+
public function timeBased($node = null): self
75+
{
76+
$clone = clone $this;
77+
$clone->factory = $clone->protoFactory->timeBased($node);
78+
$clone->entityGetter = null;
79+
80+
return $clone;
81+
}
82+
}

‎src/Symfony/Bridge/Doctrine/Tests/IdGenerator/UlidGeneratorTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/Tests/IdGenerator/UlidGeneratorTest.php
+17-2Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
use Doctrine\ORM\Mapping\Entity;
1515
use PHPUnit\Framework\TestCase;
1616
use Symfony\Bridge\Doctrine\IdGenerator\UlidGenerator;
17-
use Symfony\Component\Uid\AbstractUid;
17+
use Symfony\Component\Uid\Factory\UlidFactory;
1818
use Symfony\Component\Uid\Ulid;
1919

2020
class UlidGeneratorTest extends TestCase
@@ -25,8 +25,23 @@ public function testUlidCanBeGenerated()
2525
$generator = new UlidGenerator();
2626
$ulid = $generator->generate($em, new Entity());
2727

28-
$this->assertInstanceOf(AbstractUid::class, $ulid);
2928
$this->assertInstanceOf(Ulid::class, $ulid);
3029
$this->assertTrue(Ulid::isValid($ulid));
3130
}
31+
32+
/**
33+
* @requires function \Symfony\Component\Uid\Factory\UlidFactory::create
34+
*/
35+
public function testUlidFactory()
36+
{
37+
$ulid = new Ulid('00000000000000000000000000');
38+
$em = new EntityManager();
39+
$factory = $this->createMock(UlidFactory::class);
40+
$factory->expects($this->any())
41+
->method('create')
42+
->willReturn($ulid);
43+
$generator = new UlidGenerator($factory);
44+
45+
$this->assertSame($ulid, $generator->generate($em, new Entity()));
46+
}
3247
}
+91Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
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\Bridge\Doctrine\Tests\IdGenerator;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
16+
use Symfony\Component\Uid\Factory\UuidFactory;
17+
use Symfony\Component\Uid\NilUuid;
18+
use Symfony\Component\Uid\Uuid;
19+
use Symfony\Component\Uid\UuidV4;
20+
use Symfony\Component\Uid\UuidV6;
21+
22+
/**
23+
* @requires function \Symfony\Component\Uid\Factory\UuidFactory::create
24+
*/
25+
class UuidGeneratorTest extends TestCase
26+
{
27+
public function testUuidCanBeGenerated()
28+
{
29+
$em = new EntityManager();
30+
$generator = new UuidGenerator();
31+
$uuid = $generator->generate($em, new Entity());
32+
33+
$this->assertInstanceOf(Uuid::class, $uuid);
34+
}
35+
36+
public function testCustomUuidfactory()
37+
{
38+
$uuid = new NilUuid();
39+
$em = new EntityManager();
40+
$factory = $this->createMock(UuidFactory::class);
41+
$factory->expects($this->any())
42+
->method('create')
43+
->willReturn($uuid);
44+
$generator = new UuidGenerator($factory);
45+
46+
$this->assertSame($uuid, $generator->generate($em, new Entity()));
47+
}
48+
49+
public function testUuidfactory()
50+
{
51+
$em = new EntityManager();
52+
$generator = new UuidGenerator();
53+
$this->assertInstanceOf(UuidV6::class, $generator->generate($em, new Entity()));
54+
55+
$generator = $generator->randomBased();
56+
$this->assertInstanceOf(UuidV4::class, $generator->generate($em, new Entity()));
57+
58+
$generator = $generator->timeBased();
59+
$this->assertInstanceOf(UuidV6::class, $generator->generate($em, new Entity()));
60+
61+
$generator = $generator->nameBased('prop1', Uuid::NAMESPACE_OID);
62+
$this->assertEquals(Uuid::v5(new Uuid(Uuid::NAMESPACE_OID), '3'), $generator->generate($em, new Entity()));
63+
64+
$generator = $generator->nameBased('prop2', Uuid::NAMESPACE_OID);
65+
$this->assertEquals(Uuid::v5(new Uuid(Uuid::NAMESPACE_OID), '2'), $generator->generate($em, new Entity()));
66+
67+
$generator = $generator->nameBased('getProp4', Uuid::NAMESPACE_OID);
68+
$this->assertEquals(Uuid::v5(new Uuid(Uuid::NAMESPACE_OID), '4'), $generator->generate($em, new Entity()));
69+
70+
$factory = new UuidFactory(6, 6, 5, 5, null, Uuid::NAMESPACE_OID);
71+
$generator = new UuidGenerator($factory);
72+
$generator = $generator->nameBased('prop1');
73+
$this->assertEquals(Uuid::v5(new Uuid(Uuid::NAMESPACE_OID), '3'), $generator->generate($em, new Entity()));
74+
}
75+
}
76+
77+
class Entity
78+
{
79+
public $prop1 = 1;
80+
public $prop2 = 2;
81+
82+
public function prop1()
83+
{
84+
return 3;
85+
}
86+
87+
public function getProp4()
88+
{
89+
return 4;
90+
}
91+
}

‎src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ CHANGELOG
1010
* Added the `dispatcher` option to `debug:event-dispatcher`
1111
* Added the `event_dispatcher.dispatcher` tag
1212
* Added `assertResponseFormatSame()` in `BrowserKitAssertionsTrait`
13+
* Add support for configuring UUID factory services
1314

1415
5.2.0
1516
-----

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+35Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
use Symfony\Component\RateLimiter\Policy\TokenBucketLimiter;
3535
use Symfony\Component\Serializer\Serializer;
3636
use Symfony\Component\Translation\Translator;
37+
use Symfony\Component\Uid\Factory\UuidFactory;
3738
use Symfony\Component\Validator\Validation;
3839
use Symfony\Component\WebLink\HttpHeaderSerializer;
3940
use Symfony\Component\Workflow\WorkflowEvents;
@@ -136,6 +137,7 @@ public function getConfigTreeBuilder()
136137
$this->addSecretsSection($rootNode);
137138
$this->addNotifierSection($rootNode);
138139
$this->addRateLimiterSection($rootNode);
140+
$this->addUidSection($rootNode);
139141

140142
return $treeBuilder;
141143
}
@@ -1891,4 +1893,37 @@ private function addRateLimiterSection(ArrayNodeDefinition $rootNode)
18911893
->end()
18921894
;
18931895
}
1896+
1897+
private function addUidSection(ArrayNodeDefinition $rootNode)
1898+
{
1899+
$rootNode
1900+
->children()
1901+
->arrayNode('uid')
1902+
->info('Uid configuration')
1903+
->{class_exists(UuidFactory::class) ? 'canBeDisabled' : 'canBeEnabled'}()
1904+
->addDefaultsIfNotSet()
1905+
->children()
1906+
->enumNode('default_uuid_version')
1907+
->defaultValue(6)
1908+
->values([6, 4, 1])
1909+
->end()
1910+
->enumNode('name_based_uuid_version')
1911+
->defaultValue(5)
1912+
->values([5, 3])
1913+
->end()
1914+
->scalarNode('name_based_uuid_namespace')
1915+
->cannotBeEmpty()
1916+
->end()
1917+
->enumNode('time_based_uuid_version')
1918+
->defaultValue(6)
1919+
->values([6, 1])
1920+
->end()
1921+
->scalarNode('time_based_uuid_node')
1922+
->cannotBeEmpty()
1923+
->end()
1924+
->end()
1925+
->end()
1926+
->end()
1927+
;
1928+
}
18941929
}

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+31Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@
160160
use Symfony\Component\Translation\Command\XliffLintCommand as BaseXliffLintCommand;
161161
use Symfony\Component\Translation\PseudoLocalizationTranslator;
162162
use Symfony\Component\Translation\Translator;
163+
use Symfony\Component\Uid\Factory\UuidFactory;
164+
use Symfony\Component\Uid\UuidV4;
163165
use Symfony\Component\Validator\ConstraintValidatorInterface;
164166
use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader;
165167
use Symfony\Component\Validator\ObjectInitializerInterface;
@@ -449,6 +451,14 @@ public function load(array $configs, ContainerBuilder $container)
449451
$loader->load('web_link.php');
450452
}
451453

454+
if ($this->isConfigEnabled($container, $config['uid'])) {
455+
if (!class_exists(UuidFactory::class)) {
456+
throw new LogicException('Uid support cannot be enabled as the Uid component is not installed. Try running "composer require symfony/uid".');
457+
}
458+
459+
$this->registerUidConfiguration($config['uid'], $container, $loader);
460+
}
461+
452462
$this->addAnnotatedClassesToCompile([
453463
'**\\Controller\\',
454464
'**\\Entity\\',
@@ -2322,6 +2332,27 @@ public static function registerRateLimiter(ContainerBuilder $container, string $
23222332
$container->registerAliasForArgument($limiterId, RateLimiterFactory::class, $name.'.limiter');
23232333
}
23242334

2335+
private function registerUidConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader)
2336+
{
2337+
$loader->load('uid.php');
2338+
2339+
$container->getDefinition('uuid.factory')
2340+
->setArguments([
2341+
$config['default_uuid_version'],
2342+
$config['time_based_uuid_version'],
2343+
$config['name_based_uuid_version'],
2344+
UuidV4::class,
2345+
$config['time_based_uuid_node'] ?? null,
2346+
$config['name_based_uuid_namespace'] ?? null,
2347+
])
2348+
;
2349+
2350+
if (isset($config['name_based_uuid_namespace'])) {
2351+
$container->getDefinition('name_based_uuid.factory')
2352+
->setArguments([$config['name_based_uuid_namespace']]);
2353+
}
2354+
}
2355+
23252356
private function resolveTrustedHeaders(array $headers): int
23262357
{
23272358
$trustedHeaders = 0;

‎src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
+32Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
<xsd:element name="mailer" type="mailer" minOccurs="0" maxOccurs="1" />
3636
<xsd:element name="http-cache" type="http_cache" minOccurs="0" maxOccurs="1" />
3737
<xsd:element name="rate-limiter" type="rate_limiter" minOccurs="0" maxOccurs="1" />
38+
<xsd:element name="uid" type="uid" minOccurs="0" maxOccurs="1" />
3839
</xsd:choice>
3940

4041
<xsd:attribute name="http-method-override" type="xsd:boolean" />
@@ -692,4 +693,35 @@
692693
<xsd:attribute name="interval" type="xsd:string" />
693694
<xsd:attribute name="amount" type="xsd:int" />
694695
</xsd:complexType>
696+
697+
<xsd:complexType name="uid">
698+
<xsd:attribute name="enabled" type="xsd:boolean" />
699+
<xsd:attribute name="default_uuid_version" type="default_uuid_version" />
700+
<xsd:attribute name="name_based_uuid_version" type="name_based_uuid_version" />
701+
<xsd:attribute name="time_based_uuid_version" type="time_based_uuid_version" />
702+
<xsd:attribute name="name_based_uuid_namespace" type="xsd:string" />
703+
<xsd:attribute name="time_based_uuid_node" type="xsd:string" />
704+
</xsd:complexType>
705+
706+
<xsd:simpleType name="default_uuid_version">
707+
<xsd:restriction base="xsd:int">
708+
<xsd:enumeration value="6" />
709+
<xsd:enumeration value="4" />
710+
<xsd:enumeration value="1" />
711+
</xsd:restriction>
712+
</xsd:simpleType>
713+
714+
<xsd:simpleType name="name_based_uuid_version">
715+
<xsd:restriction base="xsd:int">
716+
<xsd:enumeration value="5" />
717+
<xsd:enumeration value="3" />
718+
</xsd:restriction>
719+
</xsd:simpleType>
720+
721+
<xsd:simpleType name="time_based_uuid_version">
722+
<xsd:restriction base="xsd:int">
723+
<xsd:enumeration value="6" />
724+
<xsd:enumeration value="1" />
725+
</xsd:restriction>
726+
</xsd:simpleType>
695727
</xsd:schema>

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.