Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle calling magic instantiation methods from within instance methods of the Enum #147

Merged
merged 3 commits into from
Jun 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased](https://github.com/BenSampo/laravel-enum/compare/v1.37.0...master)

### Added
### Fixed

- Handle calling magic instantiation methods from within instance methods of the Enum [#147](https://github.com/BenSampo/laravel-enum/pull/147)
- Add new instantiation methods `Enum::fromKey()` and `Enum::fromValue()`

### Deprecated
Expand Down
23 changes: 22 additions & 1 deletion src/Enum.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
abstract class Enum implements EnumContract
{
use Macroable {
// Because this class also defines a '__callStatic' method, a new name has to be given to the trait's '__callStatic' method.
__callStatic as macroCallStatic;
__call as macroCall;
}

/**
Expand Down Expand Up @@ -125,6 +125,27 @@ public static function __callStatic($method, $parameters)
return static::fromKey($method);
}

/**
* Delegate magic method calls to macro's or the static call.
*
* While it is not typical to use the magic instantiation dynamically, it may happen
* incidentally when calling the instantiation in an instance method of itself.
* Even when using the `static::KEY()` syntax, PHP still interprets this is a call to
* an instance method when it happens inside of an instance method of the same class.
*
* @param string $method
* @param mixed $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
if (static::hasMacro($method)) {
return $this->macroCall($method, $parameters);
}

return self::__callStatic($method, $parameters);
}

/**
* @return string
*/
Expand Down
6 changes: 6 additions & 0 deletions tests/EnumInstanceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ public function test_can_get_enum_instance_by_calling_an_enum_key_as_a_static_me
$this->assertInstanceOf(UserType::class, UserType::Administrator());
}

public function test_magic_instantiation_from_instance_method()
{
$userType = new UserType(UserType::Administrator);
$this->assertInstanceOf(UserType::class, $userType->magicInstantiationFromInstanceMethod());
}

public function test_an_exception_is_thrown_when_trying_to_get_enum_instance_by_calling_an_enum_key_as_a_static_method_which_does_not_exist()
{
$this->expectException(InvalidEnumKeyException::class);
Expand Down
14 changes: 13 additions & 1 deletion tests/EnumTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public function test_enum_to_select_array_with_string_values()
$this->assertEquals($expectedArray, $array);
}

public function test_enum_is_macroable()
public function test_enum_is_macroable_with_static_methods()
{
Enum::macro('toFlippedArray', function () {
return array_flip(self::toArray());
Expand All @@ -135,6 +135,18 @@ public function test_enum_is_macroable()
$this->assertEquals(UserType::toFlippedArray(), array_flip(UserType::toArray()));
}

public function test_enum_is_macroable_with_instance_methods()
{
Enum::macro('macroGetValue', function () {
return $this->value;
});

$this->assertTrue(UserType::hasMacro('macroGetValue'));

$user = new UserType(UserType::Administrator);
$this->assertSame(UserType::Administrator, $user->macroGetValue());
}

public function test_enum_get_instances()
{
/** @var StringValues $administrator */
Expand Down
5 changes: 5 additions & 0 deletions tests/Enums/UserType.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,9 @@ final class UserType extends Enum
const Moderator = 1;
const Subscriber = 2;
const SuperAdministrator = 3;

public function magicInstantiationFromInstanceMethod(): self
{
return self::Administrator();
}
}