From 73bd74b78b9974f2c62056bd166d88014e87c53b Mon Sep 17 00:00:00 2001 From: sneakyvv Date: Thu, 24 Aug 2023 11:42:22 +0200 Subject: [PATCH] [LiveComponent] Add priority to PreReRender hook analogue with Pre- & PostMount hooks in AsTwigComponent --- .../src/Attribute/AsLiveComponent.php | 10 +++++-- .../src/Attribute/PreReRender.php | 7 +++++ .../Unit/Attribute/AsLiveComponentTest.php | 28 ++++++++++++++++--- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/LiveComponent/src/Attribute/AsLiveComponent.php b/src/LiveComponent/src/Attribute/AsLiveComponent.php index a4660f035dd..018fd23c3cc 100644 --- a/src/LiveComponent/src/Attribute/AsLiveComponent.php +++ b/src/LiveComponent/src/Attribute/AsLiveComponent.php @@ -65,9 +65,15 @@ public static function isActionAllowed(object $component, string $action): bool * * @return \ReflectionMethod[] */ - public static function preReRenderMethods(object $component): \Traversable + public static function preReRenderMethods(object $component): iterable { - yield from self::attributeMethodsFor(PreReRender::class, $component); + $methods = iterator_to_array(self::attributeMethodsFor(PreReRender::class, $component)); + + usort($methods, static function (\ReflectionMethod $a, \ReflectionMethod $b) { + return $a->getAttributes(PreReRender::class)[0]->newInstance()->priority <=> $b->getAttributes(PreReRender::class)[0]->newInstance()->priority; + }); + + return array_reverse($methods); } /** diff --git a/src/LiveComponent/src/Attribute/PreReRender.php b/src/LiveComponent/src/Attribute/PreReRender.php index 831f8f58708..07f561b1bb5 100644 --- a/src/LiveComponent/src/Attribute/PreReRender.php +++ b/src/LiveComponent/src/Attribute/PreReRender.php @@ -22,4 +22,11 @@ #[\Attribute(\Attribute::TARGET_METHOD)] final class PreReRender { + /** + * @param int $priority If multiple hooks are registered in a component, use to configure + * the order in which they are called (higher called earlier) + */ + public function __construct(public int $priority = 0) + { + } } diff --git a/src/LiveComponent/tests/Unit/Attribute/AsLiveComponentTest.php b/src/LiveComponent/tests/Unit/Attribute/AsLiveComponentTest.php index 78c9c04f0ca..93d4ae23350 100644 --- a/src/LiveComponent/tests/Unit/Attribute/AsLiveComponentTest.php +++ b/src/LiveComponent/tests/Unit/Attribute/AsLiveComponentTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\UX\LiveComponent\Attribute\AsLiveComponent; +use Symfony\UX\LiveComponent\Attribute\PreReRender; use Symfony\UX\LiveComponent\Tests\Fixtures\Component\Component5; /** @@ -36,12 +37,31 @@ public function testCanGetPostHydrateMethods(): void $this->assertSame('method5', $methods[0]->getName()); } - public function testCanGetPreReRenderMethods(): void + public function testPreMountHooksAreOrderedByPriority(): void { - $methods = iterator_to_array(AsLiveComponent::preReRenderMethods(new Component5())); + $hooks = AsLiveComponent::preReRenderMethods( + new class() { + #[PreReRender(priority: -10)] + public function hook1() + { + } - $this->assertCount(1, $methods); - $this->assertSame('method3', $methods[0]->getName()); + #[PreReRender(priority: 10)] + public function hook2() + { + } + + #[PreReRender] + public function hook3() + { + } + } + ); + + $this->assertCount(3, $hooks); + $this->assertSame('hook2', $hooks[0]->name); + $this->assertSame('hook3', $hooks[1]->name); + $this->assertSame('hook1', $hooks[2]->name); } public function testCanGetLiveListeners(): void