Skip to content

Commit 3dc1b01

Browse files
committed
[12.x] Add enum() method to Config Repository
1 parent 2f7611e commit 3dc1b01

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

src/Illuminate/Config/Repository.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Illuminate\Config;
44

55
use ArrayAccess;
6+
use BackedEnum;
67
use Illuminate\Contracts\Config\Repository as ConfigContract;
78
use Illuminate\Support\Arr;
89
use Illuminate\Support\Collection;
@@ -200,6 +201,43 @@ public function collection(string $key, $default = null): Collection
200201
return new Collection($this->array($key, $default));
201202
}
202203

204+
/**
205+
* Get the specified configuration value as an enum.
206+
*
207+
* @template TEnum of \BackedEnum
208+
*
209+
* @param string $key
210+
* @param class-string<TEnum> $enumClass
211+
* @param (\Closure():(TEnum|null))|TEnum|null $default
212+
* @return TEnum
213+
*
214+
* @throws \InvalidArgumentException
215+
*/
216+
public function enum(string $key, string $enumClass, $default = null): BackedEnum
217+
{
218+
$value = $this->get($key, $default);
219+
220+
if ($value instanceof $enumClass) {
221+
return $value;
222+
}
223+
224+
if ($value === null || ! enum_exists($enumClass) || ! is_subclass_of($enumClass, BackedEnum::class)) {
225+
throw new InvalidArgumentException(
226+
sprintf('Configuration value for key [%s] must be a valid backed enum value, %s given.', $key, gettype($value))
227+
);
228+
}
229+
230+
$enumValue = $enumClass::tryFrom($value);
231+
232+
if ($enumValue === null) {
233+
throw new InvalidArgumentException(
234+
sprintf('Configuration value for key [%s] is not a valid value for enum [%s].', $key, $enumClass)
235+
);
236+
}
237+
238+
return $enumValue;
239+
}
240+
203241
/**
204242
* Set a given configuration value.
205243
*

tests/Config/RepositoryTest.php

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,18 @@
77
use InvalidArgumentException;
88
use PHPUnit\Framework\TestCase;
99

10+
enum TestStringBackedEnum: string
11+
{
12+
case Foo = 'foo';
13+
case Bar = 'bar';
14+
}
15+
16+
enum TestIntBackedEnum: int
17+
{
18+
case One = 1;
19+
case Two = 2;
20+
}
21+
1022
class RepositoryTest extends TestCase
1123
{
1224
/**
@@ -372,4 +384,60 @@ public function testItThrowsAnExceptionWhenTryingToGetNonFloatValueAsFloat(): vo
372384

373385
$this->repository->float('a.b');
374386
}
387+
388+
public function testItGetsAsEnumFromStringValue(): void
389+
{
390+
$this->repository->set('string_enum', 'foo');
391+
392+
$this->assertSame(
393+
TestStringBackedEnum::Foo,
394+
$this->repository->enum('string_enum', TestStringBackedEnum::class)
395+
);
396+
}
397+
398+
public function testItGetsAsEnumFromIntValue(): void
399+
{
400+
$this->repository->set('int_enum', 1);
401+
402+
$this->assertSame(
403+
TestIntBackedEnum::One,
404+
$this->repository->enum('int_enum', TestIntBackedEnum::class)
405+
);
406+
}
407+
408+
public function testItGetsAsEnumWhenValueIsAlreadyEnumInstance(): void
409+
{
410+
$this->repository->set('enum_instance', TestStringBackedEnum::Bar);
411+
412+
$this->assertSame(
413+
TestStringBackedEnum::Bar,
414+
$this->repository->enum('enum_instance', TestStringBackedEnum::class)
415+
);
416+
}
417+
418+
public function testItGetsAsEnumWithDefault(): void
419+
{
420+
$this->assertSame(
421+
TestStringBackedEnum::Foo,
422+
$this->repository->enum('non_existent_key', TestStringBackedEnum::class, TestStringBackedEnum::Foo)
423+
);
424+
}
425+
426+
public function testItThrowsAnExceptionWhenEnumValueIsInvalid(): void
427+
{
428+
$this->repository->set('invalid_enum', 'invalid');
429+
430+
$this->expectException(InvalidArgumentException::class);
431+
$this->expectExceptionMessage('Configuration value for key [invalid_enum] is not a valid value for enum');
432+
433+
$this->repository->enum('invalid_enum', TestStringBackedEnum::class);
434+
}
435+
436+
public function testItThrowsAnExceptionWhenEnumValueIsNull(): void
437+
{
438+
$this->expectException(InvalidArgumentException::class);
439+
$this->expectExceptionMessage('Configuration value for key [non_existent] must be a valid backed enum value');
440+
441+
$this->repository->enum('non_existent', TestStringBackedEnum::class);
442+
}
375443
}

0 commit comments

Comments
 (0)