Skip to content

Commit 3066192

Browse files
feat: add custom resource states, refactor naming
1 parent 2e916aa commit 3066192

File tree

10 files changed

+194
-17
lines changed

10 files changed

+194
-17
lines changed

config/stateful-resources.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
<?php
22

33
return [
4-
//
4+
/*
5+
|--------------------------------------------------------------------------
6+
| Custom States
7+
|--------------------------------------------------------------------------
8+
|
9+
| Below you may register custom resource states that you want to use inside
10+
| your stateful resources. Each state must be a valid enum class that
11+
| implements the ResourceState interface and uses the AsResourceState
12+
| trait.
13+
|
14+
*/
15+
'custom_states' => [
16+
// App\Enums\CustomResourceState::class,
17+
],
518
];

src/Builder.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@
22

33
namespace Farbcode\StatefulResources;
44

5-
use Farbcode\StatefulResources\Enums\ResourceState;
5+
use Farbcode\StatefulResources\Contracts\ResourceState;
66
use Illuminate\Support\Facades\Context;
77

8+
/**
9+
* Builder for creating resource instances with a specific state.
10+
*
11+
* @internal
12+
*/
813
class Builder
914
{
1015
private string $resourceClass;

src/Concerns/AsResourceState.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace Farbcode\StatefulResources\Concerns;
4+
5+
trait AsResourceState
6+
{
7+
/**
8+
* Get the string value of the state.
9+
*/
10+
public function value(): string
11+
{
12+
return $this->value;
13+
}
14+
15+
/**
16+
* Get the name of the state.
17+
*/
18+
public function name(): string
19+
{
20+
return $this->name;
21+
}
22+
}

src/Concerns/StatefullyLoadsAttributes.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
namespace Farbcode\StatefulResources\Concerns;
44

5-
use Farbcode\StatefulResources\Enums\ResourceState;
5+
use Farbcode\StatefulResources\Contracts\ResourceState;
6+
use Farbcode\StatefulResources\StateRegistry;
67
use Illuminate\Http\Resources\ConditionallyLoadsAttributes;
78
use Illuminate\Http\Resources\MergeValue;
89
use Illuminate\Http\Resources\MissingValue;
@@ -155,7 +156,12 @@ public function __call($method, $parameters)
155156
continue;
156157
}
157158

158-
return $this->{$singleStateMethod}(ResourceState::from($state), ...$parameters);
159+
$stateInstance = StateRegistry::tryFrom($state);
160+
if ($stateInstance === null) {
161+
continue;
162+
}
163+
164+
return $this->{$singleStateMethod}($stateInstance, ...$parameters);
159165
}
160166
}
161167

src/Contracts/ResourceState.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace Farbcode\StatefulResources\Contracts;
4+
5+
interface ResourceState
6+
{
7+
/**
8+
* Get the string value of the state.
9+
*/
10+
public function value(): string;
11+
12+
/**
13+
* Get the name of the state.
14+
*/
15+
public function name(): string;
16+
17+
/**
18+
* Create a state instance from a string value.
19+
*/
20+
public static function from(string $value): static;
21+
22+
/**
23+
* Try to create a state instance from a string value.
24+
*/
25+
public static function tryFrom(string $value): ?static;
26+
27+
/**
28+
* Get all available states.
29+
*/
30+
public static function cases(): array;
31+
}

src/Enums/ResourceState.php

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/Enums/Variant.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Farbcode\StatefulResources\Enums;
4+
5+
use Farbcode\StatefulResources\Concerns\AsResourceState;
6+
use Farbcode\StatefulResources\Contracts\ResourceState;
7+
8+
enum Variant: string implements ResourceState
9+
{
10+
use AsResourceState;
11+
12+
case Minimal = 'minimal';
13+
case Table = 'table';
14+
case Full = 'full';
15+
}

src/StateRegistry.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
namespace Farbcode\StatefulResources;
4+
5+
use Farbcode\StatefulResources\Contracts\ResourceState;
6+
use InvalidArgumentException;
7+
8+
/**
9+
* @internal
10+
*/
11+
class StateRegistry
12+
{
13+
private static array $stateClasses = [];
14+
15+
/**
16+
* Register a state enum class.
17+
*/
18+
public static function register(string $stateClass): void
19+
{
20+
if (! is_subclass_of($stateClass, ResourceState::class)) {
21+
throw new InvalidArgumentException("State class {$stateClass} must implement the ResourceState interface.");
22+
}
23+
24+
self::$stateClasses[] = $stateClass;
25+
}
26+
27+
/**
28+
* Try to find a state by value across all registered state classes.
29+
*/
30+
public static function tryFrom(string $value): ?ResourceState
31+
{
32+
foreach (self::$stateClasses as $stateClass) {
33+
$state = $stateClass::tryFrom($value);
34+
if ($state !== null) {
35+
return $state;
36+
}
37+
}
38+
39+
return null;
40+
}
41+
42+
/**
43+
* Find a state by value across all registered state classes.
44+
*/
45+
public static function from(string $value): ResourceState
46+
{
47+
$state = self::tryFrom($value);
48+
49+
if ($state === null) {
50+
throw new InvalidArgumentException("Unknown state: {$value}");
51+
}
52+
53+
return $state;
54+
}
55+
56+
/**
57+
* Get all available states from all registered classes.
58+
*/
59+
public static function all(): array
60+
{
61+
$states = [];
62+
foreach (self::$stateClasses as $stateClass) {
63+
$states = array_merge($states, $stateClass::cases());
64+
}
65+
66+
return $states;
67+
}
68+
69+
/**
70+
* Clear all registered state classes.
71+
*/
72+
public static function clear(): void
73+
{
74+
self::$stateClasses = [];
75+
}
76+
}

src/StatefulJsonResource.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
namespace Farbcode\StatefulResources;
44

55
use Farbcode\StatefulResources\Concerns\StatefullyLoadsAttributes;
6-
use Farbcode\StatefulResources\Enums\ResourceState;
6+
use Farbcode\StatefulResources\Contracts\ResourceState;
7+
use Farbcode\StatefulResources\Enums\Variant;
78
use Illuminate\Http\Resources\Json\JsonResource;
89
use Illuminate\Support\Facades\Context;
910

@@ -41,7 +42,7 @@ protected function getState(): ResourceState
4142
*/
4243
public function __construct($resource)
4344
{
44-
$this->state = Context::get('resource-state-'.static::class, ResourceState::Full);
45+
$this->state = Context::get('resource-state-'.static::class, Variant::Full);
4546
parent::__construct($resource);
4647
}
4748

@@ -56,7 +57,7 @@ public function __construct($resource)
5657
*/
5758
public static function __callStatic($method, $parameters)
5859
{
59-
$state = ResourceState::tryFrom($method);
60+
$state = StateRegistry::tryFrom($method);
6061

6162
if ($state === null) {
6263
return parent::__callStatic($method, $parameters);

src/StatefulResourcesServiceProvider.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Farbcode\StatefulResources;
44

5+
use Farbcode\StatefulResources\Enums\Variant;
56
use Spatie\LaravelPackageTools\Package;
67
use Spatie\LaravelPackageTools\PackageServiceProvider;
78

@@ -18,4 +19,21 @@ public function configurePackage(Package $package): void
1819
->name('stateful-resources')
1920
->hasConfigFile();
2021
}
22+
23+
public function bootingPackage(): void
24+
{
25+
$customStates = config()->array('stateful-resources.custom_states');
26+
27+
$this->app->singleton(StateRegistry::class, function () use ($customStates) {
28+
$registry = new StateRegistry;
29+
30+
$registry->register(Variant::class);
31+
32+
foreach ($customStates as $stateClass) {
33+
$registry->register($stateClass);
34+
}
35+
36+
return $registry;
37+
});
38+
}
2139
}

0 commit comments

Comments
 (0)