Skip to content

Commit ea52ac2

Browse files
author
Kevin Buchholz
committed
Merge branch 'release/1.1.0'
2 parents d1e95ad + 04c5fa1 commit ea52ac2

26 files changed

+624
-136
lines changed

CHANGELOG.md

+17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
# Changelog
22

3+
## NEXT RELEASE
4+
5+
6+
## 1.1.0 - 2019-04-04 - minor release
7+
8+
### Fixed
9+
- the `lint:phpmd`-script no longer searches for a non existing directory
10+
- localization for the `EnumerationValue`-message
11+
12+
### Changed
13+
- `__toString` now returns the value and not the key of the member
14+
15+
### Added
16+
- `defaultMember` method to `Enumeration`
17+
- `HasEnums` trait for laravel models
18+
19+
320
## 1.0.1 - 2019-03-07 - patch release
421

522
### Fixed

README.md

+75-8
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ Strongly typed enum implementation for Laravel. Based on [eloquent/enumeration](
2727
* [Methods](#methods)
2828
* [Validation](#validation)
2929
* [Localization](#localization)
30-
* [License information](#license-infromation)
30+
* [Model Trait](#model-trait)
31+
* [License information](#license-information)
3132

3233
## Requirements
3334

@@ -134,6 +135,14 @@ Returns a random member from the enum. Useful for factories.
134135
UserType::randomMember(); // Returns Administrator(), Moderator(), Subscriber() or SuperAdministrator()
135136
```
136137

138+
### static defaultMember(): static
139+
140+
Returns the default member for the enum. This function defaults to the first member of the enum when not overridden.
141+
142+
``` php
143+
UserType::defaultMember(); // Returns Administrator()
144+
```
145+
137146
### static membersByBlacklist(?array): array
138147

139148
Returns all members except the ones given.
@@ -142,17 +151,18 @@ Returns all members except the ones given.
142151
UserType::membersByBlacklist([UserType::Moderator()]); // Returns Administrator(), Subscriber() and SuperAdministrator()
143152
```
144153

145-
### static toSelectArray(): array
154+
### static toSelectArray(?array): array
146155

147-
Returns the enum for use in a select as value => description.
156+
Returns the enum for use in a select as value => key. It is also possible to set an optional blacklist-parameter to filter the returned values.
148157

149158
``` php
150159
UserType::toSelectArray(); // Returns [0 => 'Administrator', 1 => 'Moderator', 2 => 'Subscriber', 3 => 'SuperAdministrator']
151160
```
152161

153-
### toLocalizedSelectArray(): array
162+
### toLocalizedSelectArray(?array): array
154163

155-
Returns the enum for use in a select as value => description, where description is localized using `->localized()`.
164+
Returns the enum for use in a select as value => localizedValue, where localizedValue is localized using `->localized()`.
165+
Like `toSelectArray` it is possible to set an optional blacklist-parameter to filter the returned values.
156166

157167
``` php
158168
UserType::toLocalizedSelectArray(); // Returns [0 => 'Administrator', 1 => 'Moderator', 2 => 'Subscriber', 3 => 'Super Administrator']
@@ -161,7 +171,7 @@ UserType::toLocalizedSelectArray(); // Returns [0 => 'Administrator', 1 => 'Mode
161171
## Validation
162172

163173
### Array Validation
164-
You may validate that an enum value passed to a controller is a valid value for a given enum by using the `EnumerationValue` rule, for easier handling there are helper methods for creating the rule: `Enumeration::makeRule()`, `Enumeration::makeRuleWithWhitelist($whitelist)` and `Enumeration::makeRuleWithBlacklist($blacklist)`.
174+
You may validate that a value passed to a controller is a valid value for a given enum by using the `EnumerationValue` rule, for easier handling there are helper methods for creating the rule: `Enumeration::makeRule()`, `Enumeration::makeRuleWithWhitelist($whitelist)` and `Enumeration::makeRuleWithBlacklist($blacklist)`.
165175

166176
``` php
167177
public function store(Request $request)
@@ -223,7 +233,6 @@ return [
223233
```php
224234
// resources/lang/da/enums.php
225235
<?php
226-
227236
use App\Enums\UserType;
228237

229238
return [
@@ -235,6 +244,64 @@ return [
235244
];
236245
```
237246

247+
## Model Trait
248+
249+
You can use the `HasEnums` trait to enable automatic casting of properties to enums. When used, it also automatically checks if a value set to an enum property is valid, if not it throws an `UndefinedMemberException`.
250+
251+
To enable this functionality you will have to use the trait and set the enums property on your model.
252+
253+
```php
254+
<?php
255+
256+
namespace App\Models;
257+
258+
use App\Enums\UserType;
259+
use Illuminate\Database\Eloquent\Model;
260+
use Sourceboat\Enumeration\Traits\HasEnums;
261+
262+
class User extends Model
263+
{
264+
use HasEnums;
265+
266+
protected $enums = [
267+
'type' => UserType::class,
268+
];
269+
}
270+
```
271+
272+
The enums property is a simple mapping of model attributes to enum classes. For cases where you want an attribute to be nullable, but don't want to have a `null`-value member in your enum, you can specify this explicitly:
273+
274+
```php
275+
<?php
276+
277+
namespace App\Models;
278+
279+
use App\Enums\UserType;
280+
use Illuminate\Database\Eloquent\Model;
281+
use Sourceboat\Enumeration\Traits\HasEnums;
282+
283+
class User extends Model
284+
{
285+
use HasEnums;
286+
287+
protected $enums = [
288+
'type' => [ 'nullable' => true, 'enum' => UserType::class ],
289+
];
290+
}
291+
```
292+
293+
If the casted attribute is not set to be nullable and/or has a value not represented by the enum, you will get the default member of the enum when accessing the attribute.
294+
295+
```php
296+
// For example when the value has been changed manually in the database. Let's say the type is `10`.
297+
$type = $user->type
298+
299+
// Then the following will be the case:
300+
301+
echo $type === UserType::defaultMember(); // "true"
302+
echo $type->value; // "0"
303+
```
304+
238305
## License information
239306

240307
Much of the functionality in this Package is inspired by [bensampo/laravel-enum](https://github.com/bensampo/laravel-enum) and some code has been taken from it and modified, for example the `MakeEnumCommand.php`, the `EnumServiceProvider.php` and this readme.
@@ -248,4 +315,4 @@ This package is also licensed under the MIT license.
248315
## TODOs
249316

250317
* [x] Tests for all enumeration-functions and the rule.
251-
* [ ] Model-Trait to enable casting of enumerations and "on the fly"-validation for enumeration values on models.
318+
* [x] Model-Trait to enable casting of enumerations and "on the fly"-validation for enumeration values on models.

composer.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@
5050
"test": "vendor/bin/phpunit",
5151
"test-coverage": "vendor/bin/phpunit --coverage-html coverage",
5252
"lint:phpcs": "vendor/bin/phpcs -s",
53-
"lint:phpmd": "vendor/bin/phpmd config,src,tests text phpmd.xml"
53+
"lint:phpmd": "vendor/bin/phpmd src,tests text phpmd.xml"
5454
},
5555
"extra": {
5656
"branch-alias": {
57-
"dev-master": "1.0-dev"
57+
"dev-master": "1.1-dev"
5858
},
5959
"laravel": {
6060
"providers": [

phpcs.xml

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
<description>The coding standard for this project.</description>
44

55
<!-- files and folders to check -->
6-
<file>resources/lang</file>
76
<file>src</file>
87
<file>tests</file>
98

resources/lang/en/validation.php

-5
This file was deleted.

src/Enumeration.php

+22
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,26 @@ public static function makeRuleWithBlacklist(?array $blacklist = []): Enumeratio
152152
{
153153
return self::makeRuleWithWhitelist(self::membersByBlacklist($blacklist));
154154
}
155+
156+
/**
157+
* Get the default enum member.
158+
* Override for your own value / logic.
159+
*
160+
* @return static
161+
*/
162+
public static function defaultMember()
163+
{
164+
return collect(static::members())->first();
165+
}
166+
167+
/**
168+
* Returns a string representation of this member.
169+
*
170+
* @return string The string representation.
171+
* @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingReturnTypeHint
172+
*/
173+
public function __toString()
174+
{
175+
return (string) $this->value();
176+
}
155177
}

src/EnumerationServiceProvider.php

-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ class EnumerationServiceProvider extends ServiceProvider
1313
public function boot(): void
1414
{
1515
$this->bootCommands();
16-
17-
$this->loadTranslationsFrom(__DIR__ . '/../lang', 'laravel_enumeration');
1816
}
1917

2018
/**

src/Rules/EnumerationValue.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Eloquent\Enumeration\Exception\UndefinedMemberExceptionInterface;
66
use Illuminate\Contracts\Validation\Rule;
7+
use Illuminate\Support\Str;
78

89
class EnumerationValue implements Rule
910
{
@@ -66,7 +67,11 @@ public function passes($attribute, $value): bool
6667
*/
6768
public function message(): string
6869
{
69-
return __('laravel_enumeration::validation.enum_value');
70+
$key = 'validation.enum_value';
71+
72+
return Str::is($key, __($key))
73+
? 'The given value is not suitable for :attribute.'
74+
: __($key);
7075
}
7176

7277
/**

src/Traits/HasEnums.php

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?php
2+
3+
namespace Sourceboat\Enumeration\Traits;
4+
5+
use Eloquent\Enumeration\Exception\UndefinedMemberException;
6+
7+
/**
8+
* This trait allows for casting of model properties to enum members and
9+
* setting them via enum members.
10+
*/
11+
trait HasEnums
12+
{
13+
/**
14+
* Get the attribute-enum-mapping from this model.
15+
*
16+
* @return array
17+
*/
18+
public function getEnumsArray(): array
19+
{
20+
return $this->enums ?? [];
21+
}
22+
23+
/**
24+
* Returns whether the attribute was marked as enum.
25+
*
26+
* @param string $key
27+
* @return bool
28+
*/
29+
public function isEnumAttribute(string $key): bool
30+
{
31+
return isset($this->getEnumsArray()[$key]);
32+
}
33+
34+
/**
35+
* Get an attribute from the model.
36+
*
37+
* @param string $key
38+
* @return mixed
39+
* @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint
40+
*/
41+
public function getAttribute($key)
42+
{
43+
if ($this->isEnumAttribute($key)) {
44+
$class = $this->getEnumsArray()[$key];
45+
$nullable = false;
46+
47+
if (is_array($class)) {
48+
$nullable = $class['nullable'];
49+
$class = $class['enum'];
50+
}
51+
52+
try {
53+
return $class::memberByValue($this->getAttributeFromArray($key));
54+
} catch (UndefinedMemberException $e) {
55+
if ($nullable && is_null($this->getAttributeFromArray($key))) {
56+
return null;
57+
}
58+
59+
return $class::defaultMember();
60+
}
61+
}
62+
63+
return parent::getAttribute($key);
64+
}
65+
66+
/**
67+
* Set a given attribute on the model.
68+
*
69+
* @param string $key
70+
* @param mixed $value
71+
* @return $this
72+
* @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint
73+
*/
74+
public function setAttribute($key, $value)
75+
{
76+
if ($this->isEnumAttribute($key)) {
77+
$class = $this->getEnumsArray()[$key];
78+
$nullable = false;
79+
80+
if (is_array($class)) {
81+
$nullable = $class['nullable'];
82+
$class = $class['enum'];
83+
}
84+
85+
if ($nullable && is_null($value)) {
86+
$this->attributes[$key] = $value;
87+
88+
return $this;
89+
}
90+
91+
if (! $value instanceof $class) {
92+
$value = $class::memberByValue($value);
93+
}
94+
95+
$this->attributes[$key] = $value->value();
96+
97+
return $this;
98+
}
99+
100+
parent::setAttribute($key, $value);
101+
}
102+
}

tests/FruitType.php

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Sourceboat\Enumeration\Tests;
4+
5+
use Sourceboat\Enumeration\Enumeration;
6+
7+
/**
8+
* @method static \Sourceboat\Enumeration\Tests\FruitType BERRY()
9+
* @method static \Sourceboat\Enumeration\Tests\FruitType NUT()
10+
* @method static \Sourceboat\Enumeration\Tests\FruitType ACCESSORY_FRUIT()
11+
* @method static \Sourceboat\Enumeration\Tests\FruitType LEGUME()
12+
*/
13+
class FruitType extends Enumeration
14+
{
15+
protected static $localizationPath = 'test';
16+
17+
public const BERRY = 'berry';
18+
public const NUT = 'nut';
19+
public const ACCESSORY_FRUIT = 'accessory_fruit';
20+
public const LEGUME = 'legume';
21+
}

tests/TestEnum.php

-19
This file was deleted.

0 commit comments

Comments
 (0)