From f60ecb74777d321d0f198176eec6bd19cee04aa3 Mon Sep 17 00:00:00 2001 From: Attila Fulop Date: Mon, 16 Oct 2017 12:20:03 +0300 Subject: [PATCH] Added support for resolving enum class from 'ClassName@method' notation --- .styleci.yml | 6 ++++ LICENSE | 21 +++++++++++ src/CastsEnums.php | 35 ++++++++++++++++-- tests/AAASmokeTest.php | 2 +- tests/DynamicClassResolverTest.php | 48 +++++++++++++++++++++++++ tests/EnumAccessorTest.php | 2 +- tests/EnumMutatorTest.php | 2 +- tests/Models/Address.php | 30 ++++++++++++++++ tests/Models/AddressStatus.php | 25 +++++++++++++ tests/Models/AddressStatusResolver.php | 28 +++++++++++++++ tests/Models/AddressType.php | 22 ++++++++++++ tests/Models/Client.php | 2 +- tests/Models/Order.php | 2 +- tests/Models/OrderStatus.php | 2 +- tests/Resolvers/AddressTypeResolver.php | 30 ++++++++++++++++ tests/TestCase.php | 12 ++++++- 16 files changed, 259 insertions(+), 10 deletions(-) create mode 100644 .styleci.yml create mode 100644 LICENSE create mode 100644 tests/DynamicClassResolverTest.php create mode 100644 tests/Models/Address.php create mode 100644 tests/Models/AddressStatus.php create mode 100644 tests/Models/AddressStatusResolver.php create mode 100644 tests/Models/AddressType.php create mode 100644 tests/Resolvers/AddressTypeResolver.php diff --git a/.styleci.yml b/.styleci.yml new file mode 100644 index 0000000..8fd082a --- /dev/null +++ b/.styleci.yml @@ -0,0 +1,6 @@ +preset: psr2 + +enabled: + - align_phpdoc + - align_double_arrow + - align_equals diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a9fc680 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017 Attila Fulop + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/CastsEnums.php b/src/CastsEnums.php index e5e37f3..e44a9fc 100644 --- a/src/CastsEnums.php +++ b/src/CastsEnums.php @@ -24,7 +24,7 @@ trait CastsEnums public function getAttributeValue($key) { if ($this->isEnumAttribute($key)) { - $class = $this->enums[$key]; + $class = $this->getEnumClass($key); return $class::create($this->getAttributeFromArray($key)); } @@ -57,7 +57,7 @@ public function getAttribute($key) public function setAttribute($key, $value) { if ($this->isEnumAttribute($key)) { - $enumClass = $this->enums[$key]; + $enumClass = $this->getEnumClass($key); if (! $value instanceof $enumClass) { $value = new $enumClass($value); } @@ -82,4 +82,33 @@ private function isEnumAttribute($key) return isset($this->enums[$key]); } -} \ No newline at end of file + /** + * Returns the enum class. Supports 'FQCN\Class@method()' notation + * + * @param $key + * + * @return mixed + */ + private function getEnumClass($key) + { + $result = $this->enums[$key]; + if (strpos($result, '@')) { + $class = str_before($result, '@'); + $method = str_after($result, '@'); + + // If no namespace was set, prepend the Model's namespace to the + // class that resolves the enum class. Prevent this behavior, + // by setting the resolver class with a leading backslash + if (class_basename($class) == $class) { + $class = + str_before(get_class($this), class_basename(get_class($this))) . // namespace of the model + $class; + } + + $result = $class::$method(); + } + + return $result; + } + +} diff --git a/tests/AAASmokeTest.php b/tests/AAASmokeTest.php index 5c85b7c..4f86d6d 100644 --- a/tests/AAASmokeTest.php +++ b/tests/AAASmokeTest.php @@ -38,4 +38,4 @@ public function php_version_satisfies_requirements() . PHP_VERSION . ' found.'); } -} \ No newline at end of file +} diff --git a/tests/DynamicClassResolverTest.php b/tests/DynamicClassResolverTest.php new file mode 100644 index 0000000..f77fd54 --- /dev/null +++ b/tests/DynamicClassResolverTest.php @@ -0,0 +1,48 @@ + AddressType::SHIPPING, + 'address' => 'Richard Avenue 33' + ]); + + $this->assertInstanceOf(AddressType::class, $address->type); + } + + /** + * @test + */ + public function it_resolves_local_enum_class_name_from_the_at_notation() + { + $address = Address::create([ + 'type' => AddressType::SHIPPING, + 'address' => 'Richard Avenue 33' + ]); + + $this->assertInstanceOf(AddressStatus::class, $address->status); + } + +} diff --git a/tests/EnumAccessorTest.php b/tests/EnumAccessorTest.php index 717f496..ce7b017 100644 --- a/tests/EnumAccessorTest.php +++ b/tests/EnumAccessorTest.php @@ -95,4 +95,4 @@ public function it_doesnt_break_related_properties() } -} \ No newline at end of file +} diff --git a/tests/EnumMutatorTest.php b/tests/EnumMutatorTest.php index c9b8cbb..5d3d34e 100644 --- a/tests/EnumMutatorTest.php +++ b/tests/EnumMutatorTest.php @@ -79,4 +79,4 @@ public function it_doesnt_accept_scalars_that_arent_valid_enum_values() $order->status = 'wtf'; } -} \ No newline at end of file +} diff --git a/tests/Models/Address.php b/tests/Models/Address.php new file mode 100644 index 0000000..70f0ce3 --- /dev/null +++ b/tests/Models/Address.php @@ -0,0 +1,30 @@ + 'Konekt\\Enum\\Eloquent\\Tests\\Resolvers\\AddressTypeResolver@enumClass', + 'status' => 'AddressStatusResolver@enumClass' + ]; + +} diff --git a/tests/Models/AddressStatus.php b/tests/Models/AddressStatus.php new file mode 100644 index 0000000..7ddb4e9 --- /dev/null +++ b/tests/Models/AddressStatus.php @@ -0,0 +1,25 @@ +belongsTo(Client::class); } -} \ No newline at end of file +} diff --git a/tests/Models/OrderStatus.php b/tests/Models/OrderStatus.php index a6b74f3..270c222 100644 --- a/tests/Models/OrderStatus.php +++ b/tests/Models/OrderStatus.php @@ -24,4 +24,4 @@ class OrderStatus extends Enum const SHIPPING = 'shipping'; const COMPLETED = 'completed'; -} \ No newline at end of file +} diff --git a/tests/Resolvers/AddressTypeResolver.php b/tests/Resolvers/AddressTypeResolver.php new file mode 100644 index 0000000..3bd8a96 --- /dev/null +++ b/tests/Resolvers/AddressTypeResolver.php @@ -0,0 +1,30 @@ +capsule->bootEloquent(); $this->capsule->schema()->dropIfExists('orders'); + $this->capsule->schema()->dropIfExists('clients'); + $this->capsule->schema()->dropIfExists('addresses'); $this->capsule->schema()->create('orders', function (Blueprint $table) { $table->increments('id'); @@ -57,7 +59,15 @@ protected function setUpDatabase() $table->timestamps(); }); + $this->capsule->schema()->create('addresses', function (Blueprint $table) { + $table->increments('id'); + $table->string('type'); + $table->string('status')->nullable(); + $table->string('address')->nullable(); + $table->timestamps(); + }); + } -} \ No newline at end of file +}