Skip to content

Commit a9d0f7c

Browse files
committed
Adds EnumSerializableTrait - fixes #52
1 parent cbe58e7 commit a9d0f7c

File tree

4 files changed

+174
-0
lines changed

4 files changed

+174
-0
lines changed

composer.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
"php": ">=5.3",
2525
"ext-reflection": "*"
2626
},
27+
"suggest": {
28+
"php": "PHP>=5.4 will be required for using trait EnumSerializableTrait"
29+
},
2730
"require-dev": {
2831
"phpunit/phpunit": "~4.0"
2932
},

src/EnumSerializableTrait.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
namespace MabeEnum;
4+
5+
use RuntimeException;
6+
use LogicException;
7+
8+
/**
9+
* Trait to make enumerations serializable
10+
*
11+
* This trait is a workaround to make enumerations serializable.
12+
*
13+
* Please note that this feature breaks singleton behaviour of your enumerations
14+
* if an enumeration will be unserialized after it was instantiated already.
15+
*
16+
* @link https://github.com/marc-mabe/php-enum/issues/52 for further information about this feature
17+
* @link http://github.com/marc-mabe/php-enum for the canonical source repository
18+
* @copyright Copyright (c) 2015 Marc Bennewitz
19+
* @license http://github.com/marc-mabe/php-enum/blob/master/LICENSE.txt New BSD License
20+
*/
21+
trait EnumSerializableTrait
22+
{
23+
/**
24+
* The method will be defined by MabeEnum\Enum
25+
* @return null|bool|int|float|string
26+
*/
27+
abstract public function getValue();
28+
29+
/**
30+
* Serialized the value of the enumeration
31+
* This will be called automatically on `serialize()` if the enumeration implements the `Serializable` interface
32+
* @return string
33+
*/
34+
public function serialize()
35+
{
36+
return serialize($this->getValue());
37+
}
38+
39+
/**
40+
* Unserializes a given serialized value and push it into the current instance
41+
* This will be called automatically on `unserialize()` if the enumeration implements the `Serializable` interface
42+
* @param string
43+
* @throws RuntimeException On an unknown or invalid value
44+
* @throws LogicException On changing numeration value by calling this directly
45+
*/
46+
public function unserialize($serialized)
47+
{
48+
$value = unserialize($serialized);
49+
$constants = self::getConstants();
50+
$name = array_search($value, $constants, true);
51+
if ($name === false) {
52+
if (is_scalar($value)) {
53+
$message = 'Unknown value ' . var_export($value, true);
54+
} else {
55+
$message = 'Invalid value of type ' . (is_object($value) ? get_class($value) : gettype($value));
56+
}
57+
throw new RuntimeException($message);
58+
}
59+
60+
$class = get_class($this);
61+
$enumerator = $this;
62+
$closure = function () use ($class, $name, $value, $enumerator) {
63+
if ($this->value !== null && $value !== null) {
64+
throw new LogicException('Do not call this directly - please use unserialize($enum) instead');
65+
}
66+
67+
$this->value = $value;
68+
69+
if (!isset(self::$instances[$class][$name])) {
70+
self::$instances[$class][$name] = $enumerator;
71+
}
72+
};
73+
$closure = $closure->bindTo($this, 'MabeEnum\Enum');
74+
$closure();
75+
}
76+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
namespace MabeEnumTest;
4+
5+
use MabeEnumTest\TestAsset\SerializableEnum;
6+
use PHPUnit_Framework_TestCase as TestCase;
7+
8+
/**
9+
* Unit tests for the trait MabeEnum\EnumSerializableTrait
10+
*
11+
* @link http://github.com/marc-mabe/php-enum for the canonical source repository
12+
* @copyright Copyright (c) 2015 Marc Bennewitz
13+
* @license http://github.com/marc-mabe/php-enum/blob/master/LICENSE.txt New BSD License
14+
*/
15+
class EnumSerializableTraitTest extends TestCase
16+
{
17+
public function setUp()
18+
{
19+
if (version_compare(PHP_VERSION, '5.4', '<')) {
20+
$this->markTestSkipped('Traits require PHP-5.4');
21+
}
22+
23+
SerializableEnum::clear();
24+
}
25+
26+
public function testSerializeSerializableEnum()
27+
{
28+
$serialized = serialize(SerializableEnum::get(SerializableEnum::NIL));
29+
$this->assertInternalType('string', $serialized);
30+
31+
$unserialized = unserialize($serialized);
32+
$this->assertInstanceOf('MabeEnumTest\TestAsset\SerializableEnum', $unserialized);
33+
}
34+
35+
public function testUnserializeFirstWillHoldTheSameInstance()
36+
{
37+
$serialized = serialize(SerializableEnum::get(SerializableEnum::STR));
38+
$this->assertInternalType('string', $serialized);
39+
40+
// clear all instantiated instances so we can virtual test unserializing first
41+
SerializableEnum::clear();
42+
43+
// First unserialize
44+
$unserialized = unserialize($serialized);
45+
$this->assertInstanceOf('MabeEnumTest\TestAsset\SerializableEnum', $unserialized);
46+
47+
// second instantiate
48+
$enum = SerializableEnum::get($unserialized->getValue());
49+
50+
// check if it's the same instance
51+
$this->assertSame($enum, $unserialized);
52+
}
53+
54+
public function testUnserializeThrowsRuntimeExceptionOnUnknownValue()
55+
{
56+
$this->setExpectedException('RuntimeException');
57+
unserialize('C:39:"MabeEnumTest\TestAsset\SerializableEnum":11:{s:4:"test";}');
58+
}
59+
60+
public function testUnserializeThrowsRuntimeExceptionOnInvalidValue()
61+
{
62+
$this->setExpectedException('RuntimeException');
63+
unserialize('C:39:"MabeEnumTest\TestAsset\SerializableEnum":19:{O:8:"stdClass":0:{}}');
64+
}
65+
66+
public function testUnserializeThrowsLogicExceptionOnChangingValue()
67+
{
68+
$this->setExpectedException('LogicException');
69+
$enum = SerializableEnum::get(SerializableEnum::INT);
70+
$enum->unserialize(serialize(SerializableEnum::STR));
71+
}
72+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace MabeEnumTest\TestAsset;
4+
5+
use MabeEnum\Enum;
6+
use MabeEnum\EnumSerializableTrait;
7+
use Serializable;
8+
9+
/**
10+
* Unit tests for the class MabeEnum\EnumSerializableTrait
11+
*
12+
* @link http://github.com/marc-mabe/php-enum for the canonical source repository
13+
* @copyright Copyright (c) 2015 Marc Bennewitz
14+
* @license http://github.com/marc-mabe/php-enum/blob/master/LICENSE.txt New BSD License
15+
*/
16+
class SerializableEnum extends Enum implements Serializable
17+
{
18+
use EnumSerializableTrait;
19+
20+
const INT = 0;
21+
const NIL = null;
22+
const STR = '';
23+
}

0 commit comments

Comments
 (0)