Skip to content

Commit

Permalink
[1.x] Allow external drivers to retrieve defined features for the giv…
Browse files Browse the repository at this point in the history
…en 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 <[email protected]>
  • Loading branch information
timacdonald and timacdonald authored Nov 12, 2024
1 parent dc2b599 commit 1a3a06e
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/Contracts/DefinesFeaturesExternally.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Laravel\Pennant\Contracts;

interface DefinesFeaturesExternally
{
/**
* Retrieve the defined features for the given scope.
*
* @return list<string>
*/
public function definedFeaturesForScope(mixed $scope): array;
}
7 changes: 7 additions & 0 deletions src/Drivers/Decorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
73 changes: 73 additions & 0 deletions tests/Feature/DefinesFeaturesExternallyTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

namespace Tests\Feature;

use Illuminate\Support\Facades\Config;
use Laravel\Pennant\Contracts\DefinesFeaturesExternally;
use Laravel\Pennant\Contracts\FeatureScopeable;
use Laravel\Pennant\Drivers\ArrayDriver;
use Laravel\Pennant\Feature;
use Tests\TestCase;

class DefinesFeaturesExternallyTest extends TestCase
{
public function test_it_can_retrieve_all_features_when_features_are_defined_externally()
{
$driver = new class(app('events'), []) extends ArrayDriver implements DefinesFeaturesExternally
{
/**
* Retrieve the defined features for the given scope.
*
* @return list<string>
*/
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<string>
*/
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);
}
}

0 comments on commit 1a3a06e

Please sign in to comment.