diff --git a/framework/core/src/Api/Controller/SetSettingsController.php b/framework/core/src/Api/Controller/SetSettingsController.php index 38c8b8ca4..eca891eac 100644 --- a/framework/core/src/Api/Controller/SetSettingsController.php +++ b/framework/core/src/Api/Controller/SetSettingsController.php @@ -13,6 +13,7 @@ use Flarum\Http\RequestUtil; use Flarum\Settings\Event; use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Events\Dispatcher; +use Illuminate\Support\Arr; use Laminas\Diactoros\Response\EmptyResponse; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -20,6 +21,8 @@ use Psr\Http\Server\RequestHandlerInterface; class SetSettingsController implements RequestHandlerInterface { + public static array $resetWhen = []; + public function __construct( protected SettingsRepositoryInterface $settings, protected Dispatcher $dispatcher @@ -37,7 +40,11 @@ class SetSettingsController implements RequestHandlerInterface foreach ($settings as $k => $v) { $this->dispatcher->dispatch(new Event\Serializing($k, $v)); - $this->settings->set($k, $v); + if (! is_null($resetWhen = Arr::get(static::$resetWhen, $k)) && $resetWhen($v)) { + $this->settings->delete($k); + } else { + $this->settings->set($k, $v); + } } $this->dispatcher->dispatch(new Event\Saved($settings)); diff --git a/framework/core/src/Extend/Settings.php b/framework/core/src/Extend/Settings.php index 5cb7387b2..bc72e6d86 100644 --- a/framework/core/src/Extend/Settings.php +++ b/framework/core/src/Extend/Settings.php @@ -10,12 +10,14 @@ namespace Flarum\Extend; use Flarum\Admin\WhenSavingSettings; +use Flarum\Api\Controller\SetSettingsController; use Flarum\Api\Resource\ForumResource; use Flarum\Api\Schema\Attribute; use Flarum\Extension\Extension; use Flarum\Foundation\ContainerUtil; use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Container\Container; +use Illuminate\Support\Arr; use Illuminate\Support\Collection; class Settings implements ExtenderInterface @@ -24,6 +26,7 @@ class Settings implements ExtenderInterface private array $defaults = []; private array $lessConfigs = []; private array $resetJsCacheFor = []; + private array $resetWhen = []; /** * Serialize a setting value to the ForumSerializer attributes. @@ -62,6 +65,20 @@ class Settings implements ExtenderInterface return $this; } + /** + * Delete a custom setting value when the callback returns true. + * This allows the setting to be reset to its default value. + * + * @param string $key: The key of the setting. + * @param (callable(mixed $value): bool) $callback: The callback to determine if the setting should be reset. + */ + public function resetWhen(string $key, callable|string $callback): self + { + $this->resetWhen[$key] = $callback; + + return $this; + } + /** * Register a setting as a LESS configuration variable. * @@ -113,6 +130,16 @@ class Settings implements ExtenderInterface }); } + if (! empty($this->resetWhen)) { + foreach ($this->resetWhen as $key => $callback) { + Arr::set( + SetSettingsController::$resetWhen, + $key, + ContainerUtil::wrapCallback($callback, $container) + ); + } + } + if (! empty($this->settings)) { (new ApiResource(ForumResource::class)) ->fields(function () use ($container) { diff --git a/framework/core/tests/integration/extenders/SettingsTest.php b/framework/core/tests/integration/extenders/SettingsTest.php index 8cf38afe7..c96a882c7 100644 --- a/framework/core/tests/integration/extenders/SettingsTest.php +++ b/framework/core/tests/integration/extenders/SettingsTest.php @@ -187,6 +187,54 @@ class SettingsTest extends TestCase $this->assertEquals(null, $value); } + #[Test] + public function resetting_setting_returns_default_value() + { + $this->extend( + (new Extend\Settings()) + ->default('custom-prefix.filter_this_setting', 'extenderDefault') + ->resetWhen('custom-prefix.filter_this_setting', function (mixed $value): bool { + return $value === ''; + }) + ); + + $this->send( + $this->request('POST', '/api/settings', [ + 'authenticatedAs' => 1, + 'json' => [ + 'custom-prefix.filter_this_setting' => '' + ] + ]) + ); + + $value = $this->app() + ->getContainer() + ->make('flarum.settings') + ->get('custom-prefix.filter_this_setting'); + + $this->assertEquals('extenderDefault', $value); + } + + #[Test] + public function not_resetting_setting_returns_value() + { + $this->send( + $this->request('POST', '/api/settings', [ + 'authenticatedAs' => 1, + 'json' => [ + 'custom-prefix.filter_this_setting' => '' + ] + ]) + ); + + $value = $this->app() + ->getContainer() + ->make('flarum.settings') + ->get('custom-prefix.filter_this_setting'); + + $this->assertEquals('', $value); + } + #[Test] public function custom_less_var_does_not_work_by_default() {