From d9ad9834bc0eed5bca8b1276bd06bb2851daea74 Mon Sep 17 00:00:00 2001 From: Ulrich Pascal Ndjike Zoa Date: Sat, 29 Jun 2024 15:45:05 +0100 Subject: [PATCH 1/3] Trigger hook on parent array property --- src/Actions/CallPropertyHook.php | 5 +++++ tests/Feature/Actions/CallPropertyHookTest.php | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/Actions/CallPropertyHook.php b/src/Actions/CallPropertyHook.php index 5fdbb1a..dbaa1cb 100644 --- a/src/Actions/CallPropertyHook.php +++ b/src/Actions/CallPropertyHook.php @@ -21,6 +21,11 @@ public function __construct(protected string $hookName, protected string $proper */ public function execute(CompileContext $context, Component $component, array $arguments): mixed { + if (! isset($context->{$this->hookName}[$this->propertyName]) && str_contains($this->propertyName, '.')) { + [$this->propertyName, $additionalArgument] = explode('.', $this->propertyName, 2); + $arguments = array_merge([$additionalArgument], $arguments); + } + $hook = $context->{$this->hookName}[$this->propertyName] ?? fn () => null; return call_user_func_array( diff --git a/tests/Feature/Actions/CallPropertyHookTest.php b/tests/Feature/Actions/CallPropertyHookTest.php index 65d8756..d71ad9e 100644 --- a/tests/Feature/Actions/CallPropertyHookTest.php +++ b/tests/Feature/Actions/CallPropertyHookTest.php @@ -17,3 +17,17 @@ expect($result)->toBe('bar'); }); + +it('calls array property hooks on the component', function () { + $context = CompileContext::make(); + + $context->updating = ['foo' => fn ($prop) => $prop]; + + $component = new class extends Component + { + }; + + $result = (new CallPropertyHook('updating', 'foo.bar'))->execute($context, $component, []); + + expect($result)->toBe('bar'); +}); From 4518e79592d6a97af3d905b5cc2971d429115e8d Mon Sep 17 00:00:00 2001 From: Ulrich Pascal Ndjike Zoa Date: Wed, 3 Jul 2024 06:16:28 +0100 Subject: [PATCH 2/3] Support deep array keys hook --- src/Actions/CallPropertyHook.php | 14 ++++++++-- .../Feature/Actions/CallPropertyHookTest.php | 28 +++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/Actions/CallPropertyHook.php b/src/Actions/CallPropertyHook.php index dbaa1cb..37a3c06 100644 --- a/src/Actions/CallPropertyHook.php +++ b/src/Actions/CallPropertyHook.php @@ -3,6 +3,7 @@ namespace Livewire\Volt\Actions; use Closure; +use Illuminate\Support\Arr; use Livewire\Volt\CompileContext; use Livewire\Volt\Component; use Livewire\Volt\Contracts\Action; @@ -22,8 +23,17 @@ public function __construct(protected string $hookName, protected string $proper public function execute(CompileContext $context, Component $component, array $arguments): mixed { if (! isset($context->{$this->hookName}[$this->propertyName]) && str_contains($this->propertyName, '.')) { - [$this->propertyName, $additionalArgument] = explode('.', $this->propertyName, 2); - $arguments = array_merge([$additionalArgument], $arguments); + $hookedProperties = array_keys($context->{$this->hookName}); + + $matchingProperty = Arr::first($hookedProperties, fn ($key) => str($this->propertyName)->is("$key*")); + + if ($matchingProperty) { + $additionalArgument = str($this->propertyName)->after($matchingProperty)->chopStart('.')->value(); + + $this->propertyName = $matchingProperty; + + $arguments = array_merge([$additionalArgument], $arguments); + } } $hook = $context->{$this->hookName}[$this->propertyName] ?? fn () => null; diff --git a/tests/Feature/Actions/CallPropertyHookTest.php b/tests/Feature/Actions/CallPropertyHookTest.php index d71ad9e..8399f28 100644 --- a/tests/Feature/Actions/CallPropertyHookTest.php +++ b/tests/Feature/Actions/CallPropertyHookTest.php @@ -31,3 +31,31 @@ expect($result)->toBe('bar'); }); + +it('calls array property hooks for deep key changed on the component', function () { + $context = CompileContext::make(); + + $context->updating = ['foo' => fn ($prop) => $prop]; + + $component = new class extends Component + { + }; + + $result = (new CallPropertyHook('updating', 'foo.bar.baz'))->execute($context, $component, []); + + expect($result)->toBe('bar.baz'); +}); + +it('calls sub-key property hooks on the component', function () { + $context = CompileContext::make(); + + $context->updating = ['foo.bar' => fn ($prop) => $prop]; + + $component = new class extends Component + { + }; + + $result = (new CallPropertyHook('updating', 'foo.bar.baz'))->execute($context, $component, []); + + expect($result)->toBe('baz'); +}); From 57e18a3f1bd082330cc4d98f860dd41855f5ea01 Mon Sep 17 00:00:00 2001 From: Ulrich Pascal Ndjike Zoa Date: Wed, 3 Jul 2024 06:20:52 +0100 Subject: [PATCH 3/3] Don't use Chop method --- src/Actions/CallPropertyHook.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Actions/CallPropertyHook.php b/src/Actions/CallPropertyHook.php index 37a3c06..e0f4d65 100644 --- a/src/Actions/CallPropertyHook.php +++ b/src/Actions/CallPropertyHook.php @@ -28,7 +28,7 @@ public function execute(CompileContext $context, Component $component, array $ar $matchingProperty = Arr::first($hookedProperties, fn ($key) => str($this->propertyName)->is("$key*")); if ($matchingProperty) { - $additionalArgument = str($this->propertyName)->after($matchingProperty)->chopStart('.')->value(); + $additionalArgument = str($this->propertyName)->after($matchingProperty)->trim('.')->value(); $this->propertyName = $matchingProperty;