Skip to content

Commit b20c2d5

Browse files
author
Willem Stuursma
committed
Merge remote-tracking branch 'upstream/master' into comparator
2 parents 960cdf1 + 758bc39 commit b20c2d5

File tree

5 files changed

+108
-47
lines changed

5 files changed

+108
-47
lines changed

.travis.yml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
language: php
22

33
php:
4-
- 5.4
5-
- 5.5
6-
- 5.6
7-
- 7.0
8-
- 7.1
94
- 7.2
10-
- nightly
5+
- 7.3
116

127
matrix:
138
fast_finish: true
@@ -17,11 +12,10 @@ cache:
1712
- $HOME/.composer/cache
1813

1914
before_script:
20-
- composer install -n
15+
- travis_retry composer install -n
2116

2217
script:
2318
- vendor/bin/phpunit
24-
- vendor/bin/phpcs --standard=PSR2 ./src/
2519

2620
# Use Travis' new container-based infrastructure.
2721
# See http://docs.travis-ci.com/user/migrating-from-legacy/#How-can-I-use-container-based-infrastructure%3F

README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
## Why?
88

9-
First, and mainly, `SplEnum` is not integrated to PHP, you have to install it separately.
9+
First, and mainly, `SplEnum` is not integrated to PHP, you have to install the extension separately.
1010

1111
Using an enum instead of class constants provides the following advantages:
1212

@@ -38,8 +38,6 @@ class Action extends Enum
3838
}
3939
```
4040

41-
Note the `private` keyword requires PHP > 7.1, you can omit it on PHP 7.0.
42-
4341
## Usage
4442

4543
```php
@@ -125,4 +123,5 @@ class Action extends Enum
125123
## Related projects
126124

127125
- [Doctrine enum mapping](https://github.com/acelaya/doctrine-enum-type)
128-
- [Symfony 2/3 ParamConverter integration](https://github.com/Ex3v/MyCLabsEnumParamConverter)
126+
- [Symfony ParamConverter integration](https://github.com/Ex3v/MyCLabsEnumParamConverter)
127+
- [PHPStan integration](https://github.com/timeweb/phpstan-enum)

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
}
2323
},
2424
"require": {
25-
"php": ">=5.4"
25+
"php": ">=7.2",
26+
"ext-json": "*"
2627
},
2728
"require-dev": {
2829
"phpunit/phpunit": "^4.8.35|^5.7|^6.0",

src/Enum.php

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ abstract class Enum implements \JsonSerializable
2929
*
3030
* @var array
3131
*/
32-
protected static $cache = array();
32+
protected static $cache = [];
3333

3434
/**
3535
* Creates a new value of some type
@@ -40,8 +40,14 @@ abstract class Enum implements \JsonSerializable
4040
*/
4141
public function __construct($value)
4242
{
43+
if ($value instanceof static) {
44+
$this->value = $value->getValue();
45+
46+
return;
47+
}
48+
4349
if (!$this->isValid($value)) {
44-
throw new \UnexpectedValueException("Value '$value' is not part of the enum " . get_called_class());
50+
throw new \UnexpectedValueException("Value '$value' is not part of the enum " . \get_called_class());
4551
}
4652

4753
$this->value = $value;
@@ -74,15 +80,18 @@ public function __toString()
7480
}
7581

7682
/**
77-
* Compares one Enum with another.
83+
* Determines if Enum should be considered equal with the variable passed as a parameter.
84+
* Returns false if an argument is an object of different class or not an object.
7885
*
7986
* This method is final, for more information read https://github.com/myclabs/php-enum/issues/4
8087
*
81-
* @return bool True if Enums are equal, false if not equal
88+
* @return bool
8289
*/
83-
final public function equals(Enum $enum = null)
90+
final public function equals($variable = null): bool
8491
{
85-
return $enum !== null && $this->getValue() === $enum->getValue() && get_called_class() == get_class($enum);
92+
return $variable instanceof self
93+
&& $this->getValue() === $variable->getValue()
94+
&& \get_called_class() === \get_class($variable);
8695
}
8796

8897
/**
@@ -92,7 +101,7 @@ final public function equals(Enum $enum = null)
92101
*/
93102
public static function keys()
94103
{
95-
return array_keys(static::toArray());
104+
return \array_keys(static::toArray());
96105
}
97106

98107
/**
@@ -118,8 +127,8 @@ public static function values()
118127
*/
119128
public static function toArray()
120129
{
121-
$class = get_called_class();
122-
if (!array_key_exists($class, static::$cache)) {
130+
$class = \get_called_class();
131+
if (!isset(static::$cache[$class])) {
123132
$reflection = new \ReflectionClass($class);
124133
static::$cache[$class] = $reflection->getConstants();
125134
}
@@ -136,7 +145,7 @@ public static function toArray()
136145
*/
137146
public static function isValid($value)
138147
{
139-
return in_array($value, static::toArray(), true);
148+
return \in_array($value, static::toArray(), true);
140149
}
141150

142151
/**
@@ -150,7 +159,7 @@ public static function isValidKey($key)
150159
{
151160
$array = static::toArray();
152161

153-
return isset($array[$key]);
162+
return isset($array[$key]) || \array_key_exists($key, $array);
154163
}
155164

156165
/**
@@ -162,7 +171,7 @@ public static function isValidKey($key)
162171
*/
163172
public static function search($value)
164173
{
165-
return array_search($value, static::toArray(), true);
174+
return \array_search($value, static::toArray(), true);
166175
}
167176

168177
/**
@@ -177,11 +186,11 @@ public static function search($value)
177186
public static function __callStatic($name, $arguments)
178187
{
179188
$array = static::toArray();
180-
if (isset($array[$name])) {
189+
if (isset($array[$name]) || \array_key_exists($name, $array)) {
181190
return new static($array[$name]);
182191
}
183192

184-
throw new \BadMethodCallException("No static method or enum constant '$name' in class " . get_called_class());
193+
throw new \BadMethodCallException("No static method or enum constant '$name' in class " . \get_called_class());
185194
}
186195

187196
/**

tests/EnumTest.php

100644100755
Lines changed: 78 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ public function testCreatingEnumWithInvalidValue($value)
5252
* Contains values not existing in EnumFixture
5353
* @return array
5454
*/
55-
public function invalidValueProvider() {
55+
public function invalidValueProvider()
56+
{
5657
return array(
5758
"string" => array('test'),
5859
"int" => array(1234),
@@ -68,7 +69,8 @@ public function testToString($expected, $enumObject)
6869
$this->assertSame($expected, (string) $enumObject);
6970
}
7071

71-
public function toStringProvider() {
72+
public function toStringProvider()
73+
{
7274
return array(
7375
array(EnumFixture::FOO, new EnumFixture(EnumFixture::FOO)),
7476
array(EnumFixture::BAR, new EnumFixture(EnumFixture::BAR)),
@@ -162,22 +164,23 @@ public function testIsValid($value, $isValid)
162164
$this->assertSame($isValid, EnumFixture::isValid($value));
163165
}
164166

165-
public function isValidProvider() {
166-
return array(
167+
public function isValidProvider()
168+
{
169+
return [
167170
/**
168171
* Valid values
169172
*/
170-
array('foo', true),
171-
array(42, true),
172-
array(null, true),
173-
array(0, true),
174-
array('', true),
175-
array(false, true),
173+
['foo', true],
174+
[42, true],
175+
[null, true],
176+
[0, true],
177+
['', true],
178+
[false, true],
176179
/**
177180
* Invalid values
178181
*/
179-
array('baz', false)
180-
);
182+
['baz', false]
183+
];
181184
}
182185

183186
/**
@@ -187,6 +190,7 @@ public function testIsValidKey()
187190
{
188191
$this->assertTrue(EnumFixture::isValidKey('FOO'));
189192
$this->assertFalse(EnumFixture::isValidKey('BAZ'));
193+
$this->assertTrue(EnumFixture::isValidKey('PROBLEMATIC_NULL'));
190194
}
191195

192196
/**
@@ -199,7 +203,8 @@ public function testSearch($value, $expected)
199203
$this->assertSame($expected, EnumFixture::search($value));
200204
}
201205

202-
public function searchProvider() {
206+
public function searchProvider()
207+
{
203208
return array(
204209
array('foo', 'FOO'),
205210
array(0, 'PROBLEMATIC_NUMBER'),
@@ -219,11 +224,15 @@ public function testEquals()
219224
$foo = new EnumFixture(EnumFixture::FOO);
220225
$number = new EnumFixture(EnumFixture::NUMBER);
221226
$anotherFoo = new EnumFixture(EnumFixture::FOO);
227+
$objectOfDifferentClass = new \stdClass();
228+
$notAnObject = 'foo';
222229

223230
$this->assertTrue($foo->equals($foo));
224231
$this->assertFalse($foo->equals($number));
225232
$this->assertTrue($foo->equals($anotherFoo));
226233
$this->assertFalse($foo->equals(null));
234+
$this->assertFalse($foo->equals($objectOfDifferentClass));
235+
$this->assertFalse($foo->equals($notAnObject));
227236
}
228237

229238
/**
@@ -254,12 +263,61 @@ public function testEqualsConflictValues()
254263
*/
255264
public function testJsonSerialize()
256265
{
257-
$this->assertJsonStringEqualsJsonString('"foo"', json_encode(new EnumFixture(EnumFixture::FOO)));
258-
$this->assertJsonStringEqualsJsonString('"bar"', json_encode(new EnumFixture(EnumFixture::BAR)));
259-
$this->assertJsonStringEqualsJsonString('42', json_encode(new EnumFixture(EnumFixture::NUMBER)));
260-
$this->assertJsonStringEqualsJsonString('0', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_NUMBER)));
261-
$this->assertJsonStringEqualsJsonString('null', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_NULL)));
262-
$this->assertJsonStringEqualsJsonString('""', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_EMPTY_STRING)));
263-
$this->assertJsonStringEqualsJsonString('false', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_BOOLEAN_FALSE)));
266+
$this->assertJsonEqualsJson('"foo"', json_encode(new EnumFixture(EnumFixture::FOO)));
267+
$this->assertJsonEqualsJson('"bar"', json_encode(new EnumFixture(EnumFixture::BAR)));
268+
$this->assertJsonEqualsJson('42', json_encode(new EnumFixture(EnumFixture::NUMBER)));
269+
$this->assertJsonEqualsJson('0', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_NUMBER)));
270+
$this->assertJsonEqualsJson('null', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_NULL)));
271+
$this->assertJsonEqualsJson('""', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_EMPTY_STRING)));
272+
$this->assertJsonEqualsJson('false', json_encode(new EnumFixture(EnumFixture::PROBLEMATIC_BOOLEAN_FALSE)));
273+
}
274+
275+
public function testNullableEnum()
276+
{
277+
$this->assertNull(EnumFixture::PROBLEMATIC_NULL()->getValue());
278+
$this->assertNull((new EnumFixture(EnumFixture::PROBLEMATIC_NULL))->getValue());
279+
$this->assertNull((new EnumFixture(EnumFixture::PROBLEMATIC_NULL))->jsonSerialize());
280+
}
281+
282+
public function testBooleanEnum()
283+
{
284+
$this->assertFalse(EnumFixture::PROBLEMATIC_BOOLEAN_FALSE()->getValue());
285+
$this->assertFalse((new EnumFixture(EnumFixture::PROBLEMATIC_BOOLEAN_FALSE))->jsonSerialize());
286+
}
287+
288+
public function testConstructWithSameEnumArgument()
289+
{
290+
$enum = new EnumFixture(EnumFixture::FOO);
291+
292+
$enveloped = new EnumFixture($enum);
293+
294+
$this->assertEquals($enum, $enveloped);
295+
}
296+
297+
private function assertJsonEqualsJson($json1, $json2)
298+
{
299+
$this->assertJsonStringEqualsJsonString($json1, $json2);
300+
}
301+
302+
public function testSerialize()
303+
{
304+
// split string for Pretty CI: "Line exceeds 120 characters"
305+
$bin = '4f3a33303a224d79434c6162735c54657374735c456e756d5c456e756d4669787'.
306+
'4757265223a313a7b733a383a22002a0076616c7565223b733a333a22666f6f223b7d';
307+
308+
$this->assertEquals($bin, bin2hex(serialize(EnumFixture::FOO())));
309+
}
310+
311+
public function testUnserialize()
312+
{
313+
// split string for Pretty CI: "Line exceeds 120 characters"
314+
$bin = '4f3a33303a224d79434c6162735c54657374735c456e756d5c456e756d4669787'.
315+
'4757265223a313a7b733a383a22002a0076616c7565223b733a333a22666f6f223b7d';
316+
317+
/* @var $value EnumFixture */
318+
$value = unserialize(pack('H*', $bin));
319+
320+
$this->assertEquals(EnumFixture::FOO, $value->getValue());
321+
$this->assertTrue(EnumFixture::FOO()->equals($value));
264322
}
265323
}

0 commit comments

Comments
 (0)