Skip to content

Commit 82a9e17

Browse files
committed
[LiveComponent] Add priority to PreDehydrate & PostHydrate hooks
1 parent a3a1ae9 commit 82a9e17

File tree

5 files changed

+87
-33
lines changed

5 files changed

+87
-33
lines changed

src/LiveComponent/src/Attribute/AsLiveComponent.php

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,33 +67,27 @@ public static function isActionAllowed(object $component, string $action): bool
6767
*/
6868
public static function preReRenderMethods(object $component): iterable
6969
{
70-
$methods = iterator_to_array(self::attributeMethodsFor(PreReRender::class, $component));
71-
72-
usort($methods, static function (\ReflectionMethod $a, \ReflectionMethod $b) {
73-
return $a->getAttributes(PreReRender::class)[0]->newInstance()->priority <=> $b->getAttributes(PreReRender::class)[0]->newInstance()->priority;
74-
});
75-
76-
return array_reverse($methods);
70+
return self::attributeMethodsByPriorityFor($component, PreReRender::class);
7771
}
7872

7973
/**
8074
* @internal
8175
*
8276
* @return \ReflectionMethod[]
8377
*/
84-
public static function postHydrateMethods(object $component): \Traversable
78+
public static function postHydrateMethods(object $component): iterable
8579
{
86-
yield from self::attributeMethodsFor(PostHydrate::class, $component);
80+
return self::attributeMethodsByPriorityFor($component, PostHydrate::class);
8781
}
8882

8983
/**
9084
* @internal
9185
*
9286
* @return \ReflectionMethod[]
9387
*/
94-
public static function preDehydrateMethods(object $component): \Traversable
88+
public static function preDehydrateMethods(object $component): iterable
9589
{
96-
yield from self::attributeMethodsFor(PreDehydrate::class, $component);
90+
return self::attributeMethodsByPriorityFor($component, PreDehydrate::class);
9791
}
9892

9993
public static function liveListeners(object $component): array

src/LiveComponent/src/Attribute/PostHydrate.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,11 @@
1717
#[\Attribute(\Attribute::TARGET_METHOD)]
1818
final class PostHydrate
1919
{
20+
/**
21+
* @param int $priority If multiple hooks are registered in a component, use to configure
22+
* the order in which they are called (higher called earlier)
23+
*/
24+
public function __construct(public int $priority = 0)
25+
{
26+
}
2027
}

src/LiveComponent/src/Attribute/PreDehydrate.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,11 @@
1717
#[\Attribute(\Attribute::TARGET_METHOD)]
1818
final class PreDehydrate
1919
{
20+
/**
21+
* @param int $priority If multiple hooks are registered in a component, use to configure
22+
* the order in which they are called (higher called earlier)
23+
*/
24+
public function __construct(public int $priority = 0)
25+
{
26+
}
2027
}

src/LiveComponent/tests/Unit/Attribute/AsLiveComponentTest.php

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
16+
use Symfony\UX\LiveComponent\Attribute\PostHydrate;
17+
use Symfony\UX\LiveComponent\Attribute\PreDehydrate;
1618
use Symfony\UX\LiveComponent\Attribute\PreReRender;
1719
use Symfony\UX\LiveComponent\Tests\Fixtures\Component\Component5;
1820

@@ -21,20 +23,58 @@
2123
*/
2224
final class AsLiveComponentTest extends TestCase
2325
{
24-
public function testCanGetPreDehydrateMethods(): void
26+
public function testPreDehydrateMethodsAreOrderedByPriority(): void
2527
{
26-
$methods = iterator_to_array(AsLiveComponent::preDehydrateMethods(new Component5()));
28+
$hooks = AsLiveComponent::preDehydrateMethods(
29+
new class() {
30+
#[PreDehydrate(priority: -10)]
31+
public function hook1()
32+
{
33+
}
34+
35+
#[PreDehydrate(priority: 10)]
36+
public function hook2()
37+
{
38+
}
39+
40+
#[PreDehydrate]
41+
public function hook3()
42+
{
43+
}
44+
}
45+
);
2746

28-
$this->assertCount(1, $methods);
29-
$this->assertSame('method4', $methods[0]->getName());
47+
$this->assertCount(3, $hooks);
48+
$this->assertSame('hook2', $hooks[0]->name);
49+
$this->assertSame('hook3', $hooks[1]->name);
50+
$this->assertSame('hook1', $hooks[2]->name);
3051
}
3152

32-
public function testCanGetPostHydrateMethods(): void
53+
public function testPostHydrateMethodsAreOrderedByPriority(): void
3354
{
34-
$methods = iterator_to_array(AsLiveComponent::postHydrateMethods(new Component5()));
55+
$hooks = AsLiveComponent::postHydrateMethods(
56+
new class() {
57+
#[PostHydrate(priority: -10)]
58+
public function hook1()
59+
{
60+
}
61+
62+
#[PostHydrate(priority: 10)]
63+
public function hook2()
64+
{
65+
}
66+
67+
#[PostHydrate]
68+
public function hook3()
69+
{
70+
}
71+
}
72+
);
3573

36-
$this->assertCount(1, $methods);
37-
$this->assertSame('method5', $methods[0]->getName());
74+
$this->assertCount(3, $hooks);
75+
$this->assertSame('hook2', $hooks[0]->name);
76+
$this->assertSame('hook3', $hooks[1]->name);
77+
$this->assertSame('hook1', $hooks[2]->name);
3878
}
3979

4080
public function testPreMountHooksAreOrderedByPriority(): void

src/TwigComponent/src/Attribute/AsTwigComponent.php

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,7 @@ public function serviceConfig(): array
4545
*/
4646
public static function preMountMethods(object $component): iterable
4747
{
48-
$methods = iterator_to_array(self::attributeMethodsFor(PreMount::class, $component));
49-
50-
usort($methods, static function (\ReflectionMethod $a, \ReflectionMethod $b) {
51-
return $a->getAttributes(PreMount::class)[0]->newInstance()->priority <=> $b->getAttributes(PreMount::class)[0]->newInstance()->priority;
52-
});
53-
54-
return array_reverse($methods);
48+
return self::attributeMethodsByPriorityFor($component, PreMount::class);
5549
}
5650

5751
/**
@@ -61,13 +55,7 @@ public static function preMountMethods(object $component): iterable
6155
*/
6256
public static function postMountMethods(object $component): iterable
6357
{
64-
$methods = iterator_to_array(self::attributeMethodsFor(PostMount::class, $component));
65-
66-
usort($methods, static function (\ReflectionMethod $a, \ReflectionMethod $b) {
67-
return $a->getAttributes(PostMount::class)[0]->newInstance()->priority <=> $b->getAttributes(PostMount::class)[0]->newInstance()->priority;
68-
});
69-
70-
return array_reverse($methods);
58+
return self::attributeMethodsByPriorityFor($component, PostMount::class);
7159
}
7260

7361
/**
@@ -83,4 +71,22 @@ protected static function attributeMethodsFor(string $attribute, object $compone
8371
}
8472
}
8573
}
74+
75+
/**
76+
* @param class-string $attributeClass
77+
*
78+
* @return \ReflectionMethod[]
79+
*
80+
* @internal
81+
*/
82+
protected static function attributeMethodsByPriorityFor(object $component, string $attributeClass): array
83+
{
84+
$methods = iterator_to_array(self::attributeMethodsFor($attributeClass, $component));
85+
86+
usort($methods, static function (\ReflectionMethod $a, \ReflectionMethod $b) use ($attributeClass) {
87+
return $a->getAttributes($attributeClass)[0]->newInstance()->priority <=> $b->getAttributes($attributeClass)[0]->newInstance()->priority;
88+
});
89+
90+
return array_reverse($methods);
91+
}
8692
}

0 commit comments

Comments
 (0)