From 1a3a06e39dc2069fda05dd26181645581e8050b4 Mon Sep 17 00:00:00 2001 From: Tim MacDonald Date: Wed, 13 Nov 2024 01:58:05 +1100 Subject: [PATCH] [1.x] Allow external drivers to retrieve defined features for the given scope (#127) * Allow external drivers to retrieve defined features for the given scope * Fix code styling * Ensure scope are resolved correctly --------- Co-authored-by: timacdonald --- src/Contracts/DefinesFeaturesExternally.php | 13 ++++ src/Drivers/Decorator.php | 7 ++ .../Feature/DefinesFeaturesExternallyTest.php | 73 +++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 src/Contracts/DefinesFeaturesExternally.php create mode 100644 tests/Feature/DefinesFeaturesExternallyTest.php diff --git a/src/Contracts/DefinesFeaturesExternally.php b/src/Contracts/DefinesFeaturesExternally.php new file mode 100644 index 0000000..86e3e18 --- /dev/null +++ b/src/Contracts/DefinesFeaturesExternally.php @@ -0,0 +1,13 @@ + + */ + public function definedFeaturesForScope(mixed $scope): array; +} diff --git a/src/Drivers/Decorator.php b/src/Drivers/Decorator.php index ed0ff6c..363c9dd 100644 --- a/src/Drivers/Decorator.php +++ b/src/Drivers/Decorator.php @@ -10,6 +10,7 @@ use Illuminate\Support\Str; use Illuminate\Support\Traits\Macroable; use Laravel\Pennant\Contracts\CanListStoredFeatures; +use Laravel\Pennant\Contracts\DefinesFeaturesExternally; use Laravel\Pennant\Contracts\Driver; use Laravel\Pennant\Contracts\FeatureScopeable; use Laravel\Pennant\Events\AllFeaturesPurged; @@ -620,6 +621,12 @@ public function instance($name) */ public function definedFeaturesForScope($scope) { + $scope = $this->resolveScope($scope); + + if ($this->driver instanceof DefinesFeaturesExternally) { + return collect($this->driver->definedFeaturesForScope($scope)); + } + return collect($this->nameMap) ->only($this->defined()) ->filter(function ($resolver) use ($scope) { diff --git a/tests/Feature/DefinesFeaturesExternallyTest.php b/tests/Feature/DefinesFeaturesExternallyTest.php new file mode 100644 index 0000000..011fcae --- /dev/null +++ b/tests/Feature/DefinesFeaturesExternallyTest.php @@ -0,0 +1,73 @@ + + */ + public function definedFeaturesForScope(mixed $scope): array + { + return [ + 'feature-1', + 'feature-2', + ]; + } + }; + Feature::extend('external', fn () => $driver); + Config::set('pennant.stores.external', ['driver' => 'external']); + + $features = Feature::driver('external')->all(); + + $this->assertSame([ + 'feature-1' => false, + 'feature-2' => false, + ], $features); + } + + public function test_when_features_are_defined_externally_that_scope_is_correctly_resolved() + { + $driver = new class(app('events'), []) extends ArrayDriver implements DefinesFeaturesExternally + { + /** + * Retrieve the defined features for the given scope. + * + * @return list + */ + public function definedFeaturesForScope(mixed $scope): array + { + return [ + $scope, + ]; + } + }; + Feature::extend('external', fn () => $driver); + Config::set('pennant.stores.external', ['driver' => 'external']); + + $features = Feature::driver('external')->for(new class implements FeatureScopeable + { + public function toFeatureIdentifier(string $driver): mixed + { + return 'scope-value'; + } + })->all(); + + $this->assertSame([ + 'scope-value' => false, + ], $features); + } +}