Skip to content

Commit

Permalink
Merge pull request #136 from drealecs/improve_getKey_performance
Browse files Browse the repository at this point in the history
Improve getKey method performance
  • Loading branch information
mnapoli committed Feb 15, 2021
2 parents 9fcffe3 + be02f8d commit ea06934
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 10 deletions.
43 changes: 35 additions & 8 deletions src/Enum.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ abstract class Enum implements \JsonSerializable
*/
protected $value;

/**
* Enum key, the constant name
*
* @var string
*/
private $key;

/**
* Store existing constants in a static cache per object.
*
Expand Down Expand Up @@ -61,22 +68,29 @@ public function __construct($value)
$value = $value->getValue();
}

static::assertValidValue($value);
$this->key = static::assertValidValueReturningKey($value);

/** @psalm-var T */
$this->value = $value;
}

public function __wakeup()
{
if ($this->key === null) {
$this->key = static::search($this->value);
}
}

/**
* @param mixed $value
* @return static
* @psalm-return static<T>
*/
public static function from($value): self
{
static::assertValidValue($value);
$key = static::assertValidValueReturningKey($value);

return new static($value);
return self::__callStatic($key, []);
}

/**
Expand All @@ -93,11 +107,11 @@ public function getValue()
* Returns the enum key (i.e. the constant name).
*
* @psalm-pure
* @return mixed
* @return string
*/
public function getKey()
{
return static::search($this->value);
return $this->key;
}

/**
Expand Down Expand Up @@ -201,9 +215,22 @@ public static function isValid($value)
*/
public static function assertValidValue($value): void
{
if (!static::isValid($value)) {
self::assertValidValueReturningKey($value);
}

/**
* Asserts valid enum value
*
* @psalm-pure
* @psalm-assert T $value
*/
private static function assertValidValueReturningKey($value): string
{
if (false === ($key = static::search($value))) {
throw new \UnexpectedValueException("Value '$value' is not part of the enum " . static::class);
}

return $key;
}

/**
Expand All @@ -224,11 +251,11 @@ public static function isValidKey($key)
/**
* Return key for value
*
* @param $value
* @param mixed $value
*
* @psalm-param mixed $value
* @psalm-pure
* @return mixed
* @return string|false
*/
public static function search($value)
{
Expand Down
29 changes: 27 additions & 2 deletions tests/EnumTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ public function testFailToCreateEnumWithInvalidValueThroughNamedConstructor($val
EnumFixture::from($value);
}

public function testFailToCreateEnumWithEnumItselfThroughNamedConstructor(): void
{
$this->expectException(\UnexpectedValueException::class);
$this->expectExceptionMessage("Value 'foo' is not part of the enum " . EnumFixture::class);

EnumFixture::from(EnumFixture::FOO());
}

/**
* Contains values not existing in EnumFixture
* @return array
Expand Down Expand Up @@ -316,12 +324,13 @@ public function testSerialize()
{
// split string for Pretty CI: "Line exceeds 120 characters"
$bin = '4f3a33303a224d79434c6162735c54657374735c456e756d5c456e756d4669787'.
'4757265223a313a7b733a383a22002a0076616c7565223b733a333a22666f6f223b7d';
'4757265223a323a7b733a383a22002a0076616c7565223b733a333a22666f6f223b73'.
'3a32323a22004d79434c6162735c456e756d5c456e756d006b6579223b733a333a22464f4f223b7d';

$this->assertEquals($bin, bin2hex(serialize(EnumFixture::FOO())));
}

public function testUnserialize()
public function testUnserializeVersionWithoutKey()
{
// split string for Pretty CI: "Line exceeds 120 characters"
$bin = '4f3a33303a224d79434c6162735c54657374735c456e756d5c456e756d4669787'.
Expand All @@ -332,6 +341,22 @@ public function testUnserialize()

$this->assertEquals(EnumFixture::FOO, $value->getValue());
$this->assertTrue(EnumFixture::FOO()->equals($value));
$this->assertTrue(EnumFixture::FOO() == $value);
}

public function testUnserialize()
{
// split string for Pretty CI: "Line exceeds 120 characters"
$bin = '4f3a33303a224d79434c6162735c54657374735c456e756d5c456e756d4669787'.
'4757265223a323a7b733a383a22002a0076616c7565223b733a333a22666f6f223b73'.
'3a32323a22004d79434c6162735c456e756d5c456e756d006b6579223b733a333a22464f4f223b7d';

/* @var $value EnumFixture */
$value = unserialize(pack('H*', $bin));

$this->assertEquals(EnumFixture::FOO, $value->getValue());
$this->assertTrue(EnumFixture::FOO()->equals($value));
$this->assertTrue(EnumFixture::FOO() == $value);
}

/**
Expand Down

0 comments on commit ea06934

Please sign in to comment.