Skip to content
This repository was archived by the owner on Jul 8, 2023. It is now read-only.

Commit f5a1d32

Browse files
committed
Merge branch 'release/5.0.0'
2 parents 9f6301a + 0c2358b commit f5a1d32

28 files changed

+1343
-426
lines changed

CHANGELOG.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,26 @@
11
# Enumeration changelog
22

3-
### 4.0.0 (2013-08-13)
3+
## 5.0.0 (2013-11-11)
4+
5+
- **[BC BREAK]** Renamed classes:
6+
- `Multiton` -> `AbstractMultiton`
7+
- `Enumeration` -> `AbstractEnumeration`
8+
- **[BC BREAK]** Exceptions no longer extend `LogicException`, but instead
9+
directly extend from the base `Exception` class.
10+
- **[NEW]** Implemented `AbstractValueMultiton`, an an abstract base class for
11+
implementing multitons with values. `AbstractEnumeration` now extends from
12+
this base class.
13+
- **[NEW]** Implemented `AbstractUndefinedMemeberException`, an abstract base
14+
class for implementing custom undefined member exceptions.
15+
`UndefinedMemberException` now extends from this base class.
16+
- **[NEW]** Multiton instances now implement formal interfaces:
17+
- `AbstractMultiton` instances implement `MultitonInterface`.
18+
- `AbstractValueMultiton` instances implement `ValueMultitonInterface`.
19+
- `AbstractEnumeration` instances implement `EnumerationInterface`
20+
- **[NEW]** Implemented `membersBy()` and `membersByPredicate()` which help to
21+
retrieve sets of members by various criteria.
22+
23+
## 4.0.0 (2013-08-13)
424

525
- **[BC BREAK]** `Multiton` method name changes:
626
- `multitonInstances` -> `members`
@@ -19,7 +39,7 @@
1939
- **[NEW]** Defaulting variants of member search methods
2040
- **[MAINTENANCE]** General repository maintenance
2141

22-
### 3.0.2 (2013-03-04)
42+
## 3.0.2 (2013-03-04)
2343

2444
- **[NEW]** [Archer] integration
2545
- **[NEW]** Implemented changelog

README.md

Lines changed: 87 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
[![Build Status]][Latest build]
66
[![Test Coverage]][Test coverage report]
7+
[![Uses Semantic Versioning]][SemVer]
78

89
## Installation and documentation
910

@@ -26,9 +27,9 @@ Enumeration can be used like [C++ enumerated types]. Here is an example,
2627
representing a set of HTTP request methods:
2728

2829
```php
29-
use Eloquent\Enumeration\Enumeration;
30+
use Eloquent\Enumeration\AbstractEnumeration;
3031

31-
final class HttpRequestMethod extends Enumeration
32+
final class HttpRequestMethod extends AbstractEnumeration
3233
{
3334
const OPTIONS = 'OPTIONS';
3435
const GET = 'GET';
@@ -61,7 +62,7 @@ handleHttpRequest(HttpRequestMethod::POST(), 'http://example.org/', 'foo=bar&baz
6162
```
6263

6364
For each member of the enumeration, a single instance of the enumeration class
64-
is instantiated (that is, an instance of *HttpRequestMethod* in the above
65+
is instantiated (that is, an instance of `HttpRequestMethod` in the above
6566
example). This means that strict comparison (===) can be used to determine
6667
which member has been passed to a function:
6768

@@ -91,9 +92,9 @@ following multiton describes all of the planets in our solar system, including
9192
their masses and radii:
9293

9394
```php
94-
use Eloquent\Enumeration\Multiton;
95+
use Eloquent\Enumeration\AbstractMultiton;
9596

96-
final class Planet extends Multiton
97+
final class Planet extends AbstractMultiton
9798
{
9899
/**
99100
* Universal gravitational constant
@@ -122,8 +123,6 @@ final class Planet extends Multiton
122123

123124
protected static function initializeMembers()
124125
{
125-
parent::initializeMembers();
126-
127126
new static('MERCURY', 3.302e23, 2.4397e6);
128127
new static('VENUS', 4.869e24, 6.0518e6);
129128
new static('EARTH', 5.9742e24, 6.37814e6);
@@ -148,14 +147,7 @@ final class Planet extends Multiton
148147
$this->radius = $radius;
149148
}
150149

151-
/**
152-
* @var float
153-
*/
154150
private $mass;
155-
156-
/**
157-
* @var float
158-
*/
159151
private $radius;
160152
}
161153
```
@@ -176,7 +168,8 @@ foreach (Planet::members() as $planet) {
176168
}
177169
```
178170

179-
If you run the above script you will get something like the following output:
171+
If the above script is executed, it will produce something like the following
172+
output:
180173

181174
```
182175
Your weight on MERCURY is 66.107480
@@ -189,6 +182,83 @@ Your weight on URANUS is 158.424919
189182
Your weight on NEPTUNE is 199.055584
190183
```
191184

185+
## Enumerations and class inheritance
186+
187+
When an enumeration is defined, the intent is usually to define a set of valid
188+
values that should not change, at least within the lifetime of a program's
189+
execution.
190+
191+
Since PHP has no in-built support for enumerations, this library implements them
192+
as regular PHP classes. Classes, however, allow for much more extensibility than
193+
is desirable in a true enumeration.
194+
195+
For example, a naive enumeration implementation might allow a developer to
196+
extend the `HttpRequestMethod` class from the examples above (assuming the
197+
`final` keyword is removed):
198+
199+
```php
200+
class CustomHttpMethod extends HttpRequestMethod
201+
{
202+
const PATCH = 'PATCH';
203+
}
204+
```
205+
206+
The problem with this scenario is that all the code written to expect only the
207+
HTTP methods defined in `HttpRequestMethod` is now compromised. Anybody can
208+
extend `HttpRequestMethod` to add custom values, essentially voiding the reason
209+
for defining `HttpRequestMethod` in the first place.
210+
211+
This library provides built-in protection from these kinds of circumstances.
212+
Attempting to define an enumeration that extends another enumeration will result
213+
in an exception being thrown, unless the 'base' enumeration is abstract.
214+
215+
### Abstract enumerations
216+
217+
Assuming that there really is a need to extend `HttpRequestMethod`, the way to
218+
go about it is to define an abstract base class, then extend this class to
219+
create the desired concrete enumerations:
220+
221+
```php
222+
use Eloquent\Enumeration\AbstractEnumeration;
223+
224+
abstract class AbstractHttpRequestMethod extends AbstractEnumeration
225+
{
226+
const OPTIONS = 'OPTIONS';
227+
const GET = 'GET';
228+
const HEAD = 'HEAD';
229+
const POST = 'POST';
230+
const PUT = 'PUT';
231+
const DELETE = 'DELETE';
232+
const TRACE = 'TRACE';
233+
const CONNECT = 'CONNECT';
234+
}
235+
236+
final class HttpRequestMethod extends AbstractHttpRequestMethod {}
237+
238+
final class CustomHttpMethod extends AbstractHttpRequestMethod
239+
{
240+
const PATCH = 'PATCH';
241+
}
242+
```
243+
244+
In this way, when a developer uses a type hint for `HttpRequestMethod`, there is
245+
no chance they will ever receive the 'PATCH' method:
246+
247+
```php
248+
function handleHttpRequest(HttpRequestMethod $method, $url, $body = null)
249+
{
250+
// only handles normal requests...
251+
}
252+
253+
function handleCustomHttpRequest(
254+
CustomHttpRequestMethod $method,
255+
$url,
256+
$body = null
257+
) {
258+
// handles normal requests, and custom requests...
259+
}
260+
```
261+
192262
<!-- References -->
193263

194264
[API documentation]: http://lqnt.co/enumeration/artifacts/documentation/api/
@@ -201,5 +271,7 @@ Your weight on NEPTUNE is 199.055584
201271

202272
[Build Status]: https://api.travis-ci.org/eloquent/enumeration.png?branch=master
203273
[Latest build]: https://travis-ci.org/eloquent/enumeration
274+
[SemVer]: http://semver.org/
204275
[Test coverage report]: https://coveralls.io/r/eloquent/enumeration
205276
[Test Coverage]: https://coveralls.io/repos/eloquent/enumeration/badge.png?branch=master
277+
[Uses Semantic Versioning]: http://b.repl.ca/v1/semver-yes-brightgreen.png

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"php": ">=5.3"
1616
},
1717
"require-dev": {
18-
"icecave/archer": "1.0.0-alpha.2"
18+
"icecave/archer": "~1"
1919
},
2020
"autoload": {
2121
"psr-0": {

0 commit comments

Comments
 (0)