From cdce5af47d30ae5dedbbb515979c1bd887b8de6a Mon Sep 17 00:00:00 2001 From: Grant Holle Date: Fri, 16 Jun 2023 13:20:34 +0400 Subject: [PATCH] Allow invokable classes and closures to be used in attribute handlers --- src/Import/Hydrators/AttributeHydrator.php | 18 +++++++- tests/Unit/EloquentHydratorTest.php | 50 ++++++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/Import/Hydrators/AttributeHydrator.php b/src/Import/Hydrators/AttributeHydrator.php index c241992c..d159560f 100644 --- a/src/Import/Hydrators/AttributeHydrator.php +++ b/src/Import/Hydrators/AttributeHydrator.php @@ -14,8 +14,17 @@ class AttributeHydrator extends Hydrator public function hydrate(LdapModel $object, EloquentModel $eloquent): void { foreach ($this->getSyncAttributes() as $eloquentField => $ldapField) { + ray($this->isAttributeHandler($ldapField)); + if ($this->isAttributeHandler($ldapField)) { - app($ldapField)->handle($object, $eloquent); + $handler = is_callable($ldapField) ? $ldapField : app($ldapField); + + if (is_callable($handler)) { + $handler($object, $eloquent); + continue; + } + + $handler->handle($object, $eloquent); continue; } @@ -43,6 +52,11 @@ protected function getSyncAttributes(): array */ protected function isAttributeHandler($handler): bool { - return is_string($handler) && class_exists($handler) && method_exists($handler, 'handle'); + if (is_callable($handler)) { + return true; + } + + return is_string($handler) && class_exists($handler) && + (method_exists($handler, 'handle') || method_exists($handler, '__invoke')); } } diff --git a/tests/Unit/EloquentHydratorTest.php b/tests/Unit/EloquentHydratorTest.php index f01b4301..f26c14a7 100644 --- a/tests/Unit/EloquentHydratorTest.php +++ b/tests/Unit/EloquentHydratorTest.php @@ -48,6 +48,40 @@ public function test_attribute_hydrator() $this->assertEquals('baz', $model->foo); } + public function test_attribute_hydrator_can_use_handle_function_of_class() + { + $entry = new Entry(['bar' => 'baz']); + $model = new TestHydratorModelStub; + AttributeHydrator::with(['sync_attributes' => [TestAttributeHandlerHandleStub::class]]) + ->hydrate($entry, $model); + + $this->assertEquals('baz', $model->foo); + } + + public function test_attribute_hydrator_can_use_invokable_class() + { + $entry = new Entry(['bar' => 'baz']); + $model = new TestHydratorModelStub; + AttributeHydrator::with(['sync_attributes' => [TestAttributeHandlerInvokableStub::class]]) + ->hydrate($entry, $model); + + $this->assertEquals('baz', $model->foo); + } + + public function test_attribute_hydrator_can_use_inline_function() + { + $entry = new Entry(['bar' => 'baz']); + $model = new TestHydratorModelStub; + AttributeHydrator::with(['sync_attributes' => [ + function ($object, $eloquent) { + $eloquent->foo = $object->getFirstAttribute('bar'); + } + ]]) + ->hydrate($entry, $model); + + $this->assertEquals('baz', $model->foo); + } + public function test_password_hydrator_uses_random_password() { $entry = new Entry(['bar' => 'baz']); @@ -116,3 +150,19 @@ class TestHydratorModelStub extends Model implements LdapAuthenticatable { use AuthenticatesWithLdap; } + +class TestAttributeHandlerHandleStub +{ + public function handle($object, $eloquent) + { + $eloquent->foo = $object->getFirstAttribute('bar'); + } +} + +class TestAttributeHandlerInvokableStub +{ + public function __invoke($object, $eloquent) + { + $eloquent->foo = $object->getFirstAttribute('bar'); + } +}