Skip to content

Commit 398ff80

Browse files
committed
[HttpKernel] Add the UidValueResolver argument value resolver
1 parent a14eb3f commit 398ff80

File tree

14 files changed

+352
-0
lines changed

14 files changed

+352
-0
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface;
8181
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
8282
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\BackedEnumValueResolver;
83+
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\UidValueResolver;
8384
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
8485
use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;
8586
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
@@ -416,6 +417,8 @@ public function load(array $configs, ContainerBuilder $container)
416417
}
417418

418419
$this->registerUidConfiguration($config['uid'], $container, $loader);
420+
} else {
421+
$container->removeDefinition('argument_resolver.uid');
419422
}
420423

421424
// register cache before session so both can share the connection services
@@ -2577,6 +2580,10 @@ private function registerUidConfiguration(array $config, ContainerBuilder $conta
25772580
$container->getDefinition('name_based_uuid.factory')
25782581
->setArguments([$config['name_based_uuid_namespace']]);
25792582
}
2583+
2584+
if (!class_exists(UidValueResolver::class)) {
2585+
$container->removeDefinition('argument_resolver.uid');
2586+
}
25802587
}
25812588

25822589
private function resolveTrustedHeaders(array $headers): int

src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver;
2020
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\ServiceValueResolver;
2121
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver;
22+
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\UidValueResolver;
2223
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver;
2324
use Symfony\Component\HttpKernel\Controller\ErrorController;
2425
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
@@ -50,6 +51,11 @@
5051
'priority' => 105, // prior to the RequestAttributeValueResolver
5152
])
5253

54+
->set('argument_resolver.uid', UidValueResolver::class)
55+
->tag('controller.argument_value_resolver', [
56+
'priority' => 100, // same priority than RequestAttributeValueResolver, but registered before
57+
])
58+
5359
->set('argument_resolver.request_attribute', RequestAttributeValueResolver::class)
5460
->tag('controller.argument_value_resolver', ['priority' => 100])
5561

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller;
13+
14+
use Symfony\Component\HttpFoundation\Response;
15+
use Symfony\Component\Routing\Annotation\Route;
16+
use Symfony\Component\Uid\Ulid;
17+
use Symfony\Component\Uid\UuidV1;
18+
19+
class UidController
20+
{
21+
#[Route(path: '/1/uuid-v1/{userId}')]
22+
public function anyFormat(UuidV1 $userId): Response
23+
{
24+
return new Response($userId);
25+
}
26+
27+
#[Route(path: '/2/ulid/{id}', requirements: ['id' => '[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}'])]
28+
public function specificFormatInAttribute(Ulid $id): Response
29+
{
30+
return new Response($id);
31+
}
32+
33+
#[Route(path: '/3/uuid-v1/{id<[0123456789ABCDEFGHJKMNPQRSTVWXYZabcdefghjkmnpqrstvwxyz]{26}>}')]
34+
public function specificFormatInPath(UuidV1 $id): Response
35+
{
36+
return new Response($id);
37+
}
38+
39+
#[Route(path: '/4/uuid-v1/{postId}/custom-uid/{commentId}')]
40+
public function manyUids(UuidV1 $postId, TestCommentIdentifier $commentId): Response
41+
{
42+
return new Response($postId."\n".$commentId);
43+
}
44+
}
45+
46+
class TestCommentIdentifier extends Ulid
47+
{
48+
}

src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,7 @@ array_controller:
6060
send_email:
6161
path: /send_email
6262
defaults: { _controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\EmailController::indexAction }
63+
64+
uid:
65+
resource: "../../Controller/UidController.php"
66+
type: "annotation"
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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\Bundle\FrameworkBundle\Tests\Functional;
13+
14+
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\UidController;
15+
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\UidValueResolver;
16+
use Symfony\Component\Uid\Ulid;
17+
use Symfony\Component\Uid\UuidV1;
18+
use Symfony\Component\Uid\UuidV4;
19+
use Symfony\Component\Uid\UuidV6;
20+
21+
/**
22+
* @see UidController
23+
*/
24+
class UidTest extends AbstractWebTestCase
25+
{
26+
protected function setUp(): void
27+
{
28+
parent::setUp();
29+
30+
self::deleteTmpDir();
31+
}
32+
33+
public function testArgumentValueResolverDisabled()
34+
{
35+
$this->expectException(\TypeError::class);
36+
$this->expectExceptionMessage('Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\UidController::anyFormat(): Argument #1 ($userId) must be of type Symfony\Component\Uid\UuidV1, string given');
37+
38+
$client = $this->createClient(['test_case' => 'Uid', 'root_config' => 'config_disabled.yml']);
39+
40+
$client->request('GET', '/1/uuid-v1/'.new UuidV1());
41+
}
42+
43+
public function testArgumentValueResolverEnabled()
44+
{
45+
if (!class_exists(UidValueResolver::class)) {
46+
$this->markTestSkipped('Needs symfony/http-kernel >= 6.1');
47+
}
48+
49+
$client = $this->createClient(['test_case' => 'Uid', 'root_config' => 'config_enabled.yml']);
50+
51+
// Any format
52+
$client->request('GET', '/1/uuid-v1/'.$uuidV1 = new UuidV1());
53+
$this->assertSame((string) $uuidV1, $client->getResponse()->getContent());
54+
$client->request('GET', '/1/uuid-v1/'.$uuidV1->toBase58());
55+
$this->assertSame((string) $uuidV1, $client->getResponse()->getContent());
56+
$client->request('GET', '/1/uuid-v1/'.$uuidV1->toRfc4122());
57+
$this->assertSame((string) $uuidV1, $client->getResponse()->getContent());
58+
// Bad version
59+
$client->request('GET', '/1/uuid-v1/'.$uuidV4 = new UuidV4());
60+
$this->assertSame(404, $client->getResponse()->getStatusCode());
61+
62+
// Only base58 format
63+
$client->request('GET', '/2/ulid/'.($ulid = new Ulid())->toBase58());
64+
$this->assertSame((string) $ulid, $client->getResponse()->getContent());
65+
$client->request('GET', '/2/ulid/'.$ulid);
66+
$this->assertSame(404, $client->getResponse()->getStatusCode());
67+
$client->request('GET', '/2/ulid/'.$ulid->toRfc4122());
68+
$this->assertSame(404, $client->getResponse()->getStatusCode());
69+
70+
// Only base32 format
71+
$client->request('GET', '/3/uuid-v1/'.$uuidV1->toBase32());
72+
$this->assertSame((string) $uuidV1, $client->getResponse()->getContent());
73+
$client->request('GET', '/3/uuid-v1/'.$uuidV1);
74+
$this->assertSame(404, $client->getResponse()->getStatusCode());
75+
$client->request('GET', '/3/uuid-v1/'.$uuidV1->toBase58());
76+
$this->assertSame(404, $client->getResponse()->getStatusCode());
77+
// Bad version
78+
$client->request('GET', '/3/uuid-v1/'.(new UuidV6())->toBase32());
79+
$this->assertSame(404, $client->getResponse()->getStatusCode());
80+
81+
// Any format for both
82+
$client->request('GET', '/4/uuid-v1/'.$uuidV1.'/custom-uid/'.$ulid->toRfc4122());
83+
$this->assertSame($uuidV1."\n".$ulid, $client->getResponse()->getContent());
84+
$client->request('GET', '/4/uuid-v1/'.$uuidV1->toBase58().'/custom-uid/'.$ulid->toBase58());
85+
$this->assertSame($uuidV1."\n".$ulid, $client->getResponse()->getContent());
86+
// Bad version
87+
$client->request('GET', '/4/uuid-v1/'.$uuidV4.'/custom-uid/'.$ulid);
88+
$this->assertSame(404, $client->getResponse()->getStatusCode());
89+
}
90+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
13+
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle;
14+
15+
return [
16+
new FrameworkBundle(),
17+
new TestBundle(),
18+
];
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
imports:
2+
- { resource: "../config/default.yml" }
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
imports:
2+
- { resource: "../config/default.yml" }
3+
4+
framework:
5+
uid: ~
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
uid:
2+
resource: "@TestBundle/Resources/config/routing.yml"

src/Symfony/Bundle/FrameworkBundle/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
"symfony/workflow": "^5.4|^6.0",
6363
"symfony/yaml": "^5.4|^6.0",
6464
"symfony/property-info": "^5.4|^6.0",
65+
"symfony/uid": "^5.4|^6.0",
6566
"symfony/web-link": "^5.4|^6.0",
6667
"phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
6768
"paragonie/sodium_compat": "^1.8",

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy