diff --git a/src/Drivers/ArrayDriver.php b/src/Drivers/ArrayDriver.php index 9051a91..40b80db 100644 --- a/src/Drivers/ArrayDriver.php +++ b/src/Drivers/ArrayDriver.php @@ -3,11 +3,10 @@ namespace Laravel\Pennant\Drivers; use Illuminate\Contracts\Events\Dispatcher; -use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Collection; use Laravel\Pennant\Contracts\Driver; use Laravel\Pennant\Events\UnknownFeatureResolved; -use RuntimeException; +use Laravel\Pennant\Feature; use stdClass; class ArrayDriver implements Driver @@ -99,7 +98,7 @@ public function getAll($features): array */ public function get($feature, $scope): mixed { - $scopeKey = $this->serializeScope($scope); + $scopeKey = Feature::serializeScope($scope); if (isset($this->resolvedFeatureStates[$feature][$scopeKey])) { return $this->resolvedFeatureStates[$feature][$scopeKey]; @@ -145,7 +144,7 @@ public function set($feature, $scope, $value): void { $this->resolvedFeatureStates[$feature] ??= []; - $this->resolvedFeatureStates[$feature][$this->serializeScope($scope)] = $value; + $this->resolvedFeatureStates[$feature][Feature::serializeScope($scope)] = $value; } /** @@ -171,7 +170,7 @@ public function setForAllScopes($feature, $value): void */ public function delete($feature, $scope): void { - unset($this->resolvedFeatureStates[$feature][$this->serializeScope($scope)]); + unset($this->resolvedFeatureStates[$feature][Feature::serializeScope($scope)]); } /** @@ -210,21 +209,4 @@ public function flushCache() { $this->resolvedFeatureStates = []; } - - /** - * Serialize the given scope for storage. - * - * @param mixed $scope - * @return string - */ - protected function serializeScope($scope) - { - return match (true) { - $scope === null => '__laravel_null', - is_string($scope) => $scope, - is_numeric($scope) => (string) $scope, - $scope instanceof Model => $scope::class.'|'.$scope->getKey(), - default => throw new RuntimeException('Unable to serialize the feature scope to a string. You should implement the FeatureScopeable contract.') - }; - } } diff --git a/src/Drivers/DatabaseDriver.php b/src/Drivers/DatabaseDriver.php index 22a4fdf..b83dd8f 100644 --- a/src/Drivers/DatabaseDriver.php +++ b/src/Drivers/DatabaseDriver.php @@ -4,12 +4,11 @@ use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Database\Connection; -use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Carbon; use Illuminate\Support\Collection; use Laravel\Pennant\Contracts\Driver; use Laravel\Pennant\Events\UnknownFeatureResolved; -use RuntimeException; +use Laravel\Pennant\Feature; use stdClass; class DatabaseDriver implements Driver @@ -102,7 +101,7 @@ public function getAll($features): array $features = Collection::make($features) ->map(fn ($scopes, $feature) => Collection::make($scopes) ->each(fn ($scope) => $query->orWhere( - fn ($q) => $q->where('name', $feature)->where('scope', $this->serializeScope($scope)) + fn ($q) => $q->where('name', $feature)->where('scope', Feature::serializeScope($scope)) ))); $records = $query->get(); @@ -110,7 +109,7 @@ public function getAll($features): array $inserts = new Collection; $results = $features->map(fn ($scopes, $feature) => $scopes->map(function ($scope) use ($feature, $records, $inserts) { - $filtered = $records->where('name', $feature)->where('scope', $this->serializeScope($scope)); + $filtered = $records->where('name', $feature)->where('scope', Feature::serializeScope($scope)); if ($filtered->isNotEmpty()) { return json_decode($filtered->value('value'), flags: JSON_OBJECT_AS_ARRAY | JSON_THROW_ON_ERROR); @@ -123,7 +122,7 @@ public function getAll($features): array $inserts[] = [ 'name' => $feature, - 'scope' => $this->serializeScope($scope), + 'scope' => Feature::serializeScope($scope), 'value' => json_encode($value, flags: JSON_THROW_ON_ERROR), ]; @@ -172,7 +171,7 @@ protected function retrieve($feature, $scope) { return $this->newQuery() ->where('name', $feature) - ->where('scope', $this->serializeScope($scope)) + ->where('scope', Feature::serializeScope($scope)) ->first(); } @@ -236,7 +235,7 @@ protected function update($feature, $scope, $value) { $exists = $this->newQuery() ->where('name', $feature) - ->where('scope', $serialized = $this->serializeScope($scope)) + ->where('scope', $serialized = Feature::serializeScope($scope)) ->exists(); if (! $exists) { @@ -266,7 +265,7 @@ protected function insert($feature, $scope, $value) { return $this->newQuery()->insert([ 'name' => $feature, - 'scope' => $this->serializeScope($scope), + 'scope' => Feature::serializeScope($scope), 'value' => json_encode($value, flags: JSON_THROW_ON_ERROR), 'created_at' => Carbon::now(), 'updated_at' => Carbon::now(), @@ -283,7 +282,7 @@ public function delete($feature, $scope): void { $this->newQuery() ->where('name', $feature) - ->where('scope', $this->serializeScope($scope)) + ->where('scope', Feature::serializeScope($scope)) ->delete(); } @@ -303,23 +302,6 @@ public function purge($features): void } } - /** - * Serialize the given scope for storage. - * - * @param mixed $scope - * @return string|null - */ - protected function serializeScope($scope) - { - return match (true) { - $scope === null => '__laravel_null', - is_string($scope) => $scope, - is_numeric($scope) => (string) $scope, - $scope instanceof Model => $scope::class.'|'.$scope->getKey(), - default => throw new RuntimeException('Unable to serialize the feature scope to a string. You should implement the FeatureScopeable contract.') - }; - } - /** * Create a new table query. * diff --git a/src/Feature.php b/src/Feature.php index 6aac7bf..0043e94 100644 --- a/src/Feature.php +++ b/src/Feature.php @@ -2,7 +2,9 @@ namespace Laravel\Pennant; +use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\Facade; +use RuntimeException; /** * @method static mixed store(string|null $store = null) @@ -60,4 +62,21 @@ protected static function getFacadeAccessor() { return FeatureManager::class; } + + /** + * Serialize the given scope for storage. + * + * @param mixed $scope + * @return string|null + */ + public static function serializeScope($scope) + { + return match (true) { + $scope === null => '__laravel_null', + is_string($scope) => $scope, + is_numeric($scope) => (string) $scope, + $scope instanceof Model => $scope::class.'|'.$scope->getKey(), + default => throw new RuntimeException('Unable to serialize the feature scope to a string. You should implement the FeatureScopeable contract.') + }; + } }