diff --git a/docs/basic-usage.md b/docs/basic-usage.md index 0030fa2..fe07135 100644 --- a/docs/basic-usage.md +++ b/docs/basic-usage.md @@ -43,6 +43,12 @@ If you ever need to completely remove all settings from their persistent storage service('settings')->flush(); ``` +Also, you can use the `take()` method to retrieve a setting and then remove it from the persistent storage in one go. This is useful when you want to retrieve a value and ensure it is no longer available for future use. + +```php +$siteName = service('settings')->take('App.siteName'); +``` + ### Contextual Settings In addition to the default behavior describe above, `Settings` can be used to define "contextual settings". diff --git a/src/Handlers/ArrayHandler.php b/src/Handlers/ArrayHandler.php index 29467ee..0fff33c 100644 --- a/src/Handlers/ArrayHandler.php +++ b/src/Handlers/ArrayHandler.php @@ -47,6 +47,15 @@ public function forget(string $class, string $property, ?string $context = null) $this->forgetStored($class, $property, $context); } + public function take(string $class, string $property, ?string $context = null): mixed + { + $value = $this->get($class, $property, $context); + + $this->forget($class, $property, $context); + + return $value; + } + public function flush() { $this->general = []; diff --git a/src/Handlers/BaseHandler.php b/src/Handlers/BaseHandler.php index d8b01a5..3778740 100644 --- a/src/Handlers/BaseHandler.php +++ b/src/Handlers/BaseHandler.php @@ -50,6 +50,21 @@ public function forget(string $class, string $property, ?string $context = null) throw new RuntimeException('Forget method not implemented for current Settings handler.'); } + /** + * If the Handler supports pulling values, it + * MUST override this method to provide that functionality. + * Not all Handlers will support writing values. + * Must throw RuntimeException for any failures. + * + * @return mixed + * + * @throws RuntimeException + */ + public function take(string $class, string $property, ?string $context = null) + { + throw new RuntimeException('Pull method not implemented for current Settings handler.'); + } + /** * All handlers MUST support flushing all values. * diff --git a/src/Handlers/DatabaseHandler.php b/src/Handlers/DatabaseHandler.php index d93b34c..05ad017 100644 --- a/src/Handlers/DatabaseHandler.php +++ b/src/Handlers/DatabaseHandler.php @@ -140,6 +140,21 @@ public function forget(string $class, string $property, ?string $context = null) $this->forgetStored($class, $property, $context); } + /** + * Retrieves a value from persistent storage + * and deletes it from the local cache. + * + * @return mixed|null + */ + public function take(string $class, string $property, ?string $context = null): mixed + { + $value = $this->get($class, $property, $context); + + $this->forget($class, $property, $context); + + return $value; + } + /** * Deletes all records from persistent storage, if found, * and from the local cache. diff --git a/src/Settings.php b/src/Settings.php index cd4e577..2806190 100644 --- a/src/Settings.php +++ b/src/Settings.php @@ -101,6 +101,20 @@ public function forget(string $key, ?string $context = null) } } + /** + * Retrieves a value from the persistent storage and removes it. + * + * @return mixed + */ + public function take(string $key, ?string $context = null) + { + [$class, $property] = $this->prepareClassAndProperty($key); + + foreach ($this->getWriteHandlers() as $handler) { + return $handler->take($class, $property, $context); + } + } + /** * Removes all settings from the persistent storage, * Useful during testing. Use with caution. diff --git a/tests/DatabaseHandlerTest.php b/tests/DatabaseHandlerTest.php index 7e77682..06ee348 100644 --- a/tests/DatabaseHandlerTest.php +++ b/tests/DatabaseHandlerTest.php @@ -211,6 +211,26 @@ public function testForgetSuccess() ]); } + public function testPullSuccess() + { + $this->hasInDatabase($this->table, [ + 'class' => 'Tests\Support\Config\Example', + 'key' => 'siteName', + 'value' => 'foo', + 'created_at' => Time::now()->toDateTimeString(), + 'updated_at' => Time::now()->toDateTimeString(), + ]); + + $value = $this->settings->take('Example.siteName'); + + $this->dontSeeInDatabase($this->table, [ + 'class' => 'Tests\Support\Config\Example', + 'key' => 'siteName', + ]); + + $this->assertSame('foo', $value); + } + public function testForgetWithNoStoredRecord() { $this->settings->forget('Example.siteName'); diff --git a/tests/SettingsTest.php b/tests/SettingsTest.php index a519142..0236528 100644 --- a/tests/SettingsTest.php +++ b/tests/SettingsTest.php @@ -70,4 +70,24 @@ public function testForgetWithContext() $this->assertSame('Bar', $this->settings->get('Example.siteName', 'category:disease')); } + + public function testPullWithContext() + { + $this->settings->set('Example.siteName', 'Amnesia', 'category:disease'); + + $value = $this->settings->take('Example.siteName', 'category:disease'); + + $this->assertSame('Amnesia', $value); + $this->assertSame('Settings Test', $this->settings->get('Example.siteName', 'category:disease')); + } + + public function testPullWithoutContext() + { + $this->settings->set('Example.siteName', 'NoContext'); + + $value = $this->settings->take('Example.siteName'); + + $this->assertSame('NoContext', $value); + $this->assertSame('Settings Test', $this->settings->get('Example.siteName')); + } }