feat: Default Settings Extender (#3127)

Co-authored-by: Alexander Skvortsov <38059171+askvortsov1@users.noreply.github.com>
This commit is contained in:
Sami Mazouz 2021-10-31 21:09:06 +01:00 committed by GitHub
parent fa82773cc8
commit ba493a90c1
6 changed files with 158 additions and 5 deletions

View File

@ -9,6 +9,7 @@
namespace Flarum\Database;
use Flarum\Extend\Settings;
use Flarum\Settings\DatabaseSettingsRepository;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\Builder;
@ -120,6 +121,9 @@ abstract class Migration
/**
* Add default values for config values.
*
* @deprecated Use the Settings extender's `default` method instead to register settings.
* @see Settings::default()
*/
public static function addSettings(array $defaults)
{

View File

@ -15,10 +15,12 @@ use Flarum\Extension\Extension;
use Flarum\Foundation\ContainerUtil;
use Flarum\Settings\SettingsRepositoryInterface;
use Illuminate\Contracts\Container\Container;
use Illuminate\Support\Collection;
class Settings implements ExtenderInterface
{
private $settings = [];
private $defaults = [];
/**
* Serialize a setting value to the ForumSerializer attributes.
@ -33,7 +35,8 @@ class Settings implements ExtenderInterface
* The callable should return:
* - mixed $value: The modified value.
*
* @param mixed $default: Optional default serialized value. Will be run through the optional callback.
* @todo remove $default in 2.0
* @param mixed $default: Deprecated optional default serialized value. Will be run through the optional callback.
* @return self
*/
public function serializeToForum(string $attributeName, string $key, $callback = null, $default = null): self
@ -43,8 +46,35 @@ class Settings implements ExtenderInterface
return $this;
}
/**
* Set a default value for a setting.
* Replaces inserting the default value with a migration.
*
* @param string $key: The setting key, must be unique. Namespace it with the extension ID (example: 'my-extension-id.setting_key').
* @param mixed $value: The setting value.
* @return self
*/
public function default(string $key, $value): self
{
$this->defaults[$key] = $value;
return $this;
}
public function extend(Container $container, Extension $extension = null)
{
if (! empty($this->defaults)) {
$container->extend('flarum.settings.default', function (Collection $defaults) {
foreach ($this->defaults as $key => $value) {
if ($defaults->has($key)) {
throw new \RuntimeException("Cannot modify immutable default setting $key.");
}
$defaults->put($key, $value);
}
});
}
if (! empty($this->settings)) {
AbstractSerializer::addAttributeMutator(
ForumSerializer::class,

View File

@ -0,0 +1,47 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Settings;
use Illuminate\Support\Collection;
class DefaultSettingsRepository implements SettingsRepositoryInterface
{
protected $defaults;
private $inner;
public function __construct(SettingsRepositoryInterface $inner, Collection $defaults)
{
$this->inner = $inner;
$this->defaults = $defaults;
}
public function get($key, $default = null)
{
// Global default overrules local default because local default is deprecated,
// and will be removed in 2.0
return $this->inner->get($key, $this->defaults->get($key, $default));
}
public function set($key, $value)
{
$this->inner->set($key, $value);
}
public function delete($keyLike)
{
$this->inner->delete($keyLike);
}
public function all(): array
{
return array_merge($this->defaults->toArray(), $this->inner->all());
}
}

View File

@ -13,6 +13,13 @@ interface SettingsRepositoryInterface
{
public function all(): array;
/**
* @todo remove $default in 2.0
*
* @param $key
* @param mixed $default: Deprecated
* @return mixed
*/
public function get($key, $default = null);
public function set($key, $value);

View File

@ -12,6 +12,7 @@ namespace Flarum\Settings;
use Flarum\Foundation\AbstractServiceProvider;
use Illuminate\Contracts\Container\Container;
use Illuminate\Database\ConnectionInterface;
use Illuminate\Support\Collection;
class SettingsServiceProvider extends AbstractServiceProvider
{
@ -20,11 +21,18 @@ class SettingsServiceProvider extends AbstractServiceProvider
*/
public function register()
{
$this->container->singleton('flarum.settings.default', function () {
return new Collection();
});
$this->container->singleton(SettingsRepositoryInterface::class, function (Container $container) {
return new MemoryCacheSettingsRepository(
new DatabaseSettingsRepository(
$container->make(ConnectionInterface::class)
)
return new DefaultSettingsRepository(
new MemoryCacheSettingsRepository(
new DatabaseSettingsRepository(
$container->make(ConnectionInterface::class)
)
),
$container->make('flarum.settings.default')
);
});

View File

@ -163,6 +163,63 @@ class SettingsTest extends TestCase
$this->assertArrayHasKey('customPrefix.noCustomSetting', $payload['data']['attributes']);
$this->assertEquals('customDefaultModified2', $payload['data']['attributes']['customPrefix.noCustomSetting']);
}
/**
* @test
*/
public function custom_setting_default_prioritizes_extender()
{
$this->extend(
(new Extend\Settings())
->serializeToForum('customPrefix.unavailableCustomSetting3', 'custom-prefix.unavailable_custom_setting3')
->default('custom-prefix.unavailable_custom_setting3', 'extenderDefault')
);
$value = $this->app()
->getContainer()
->make('flarum.settings')
->get('custom-prefix.unavailable_custom_setting3', 'defaultParameterValue');
$this->assertEquals('extenderDefault', $value);
}
/**
* @test
*/
public function custom_setting_default_falls_back_to_parameter()
{
$this->extend(
(new Extend\Settings())
->serializeToForum('customPrefix.unavailableCustomSetting4', 'custom-prefix.unavailable_custom_setting4')
);
$value = $this->app()
->getContainer()
->make('flarum.settings')
->get('custom-prefix.unavailable_custom_setting4', 'defaultParameterValue');
$this->assertEquals('defaultParameterValue', $value);
}
/**
* @test
*/
public function null_custom_setting_returns_null()
{
$this->setting('custom-prefix.custom_null_setting', null);
$this->extend(
(new Extend\Settings())
->default('custom-prefix.custom_null_setting', 'extenderDefault')
);
$value = $this->app()
->getContainer()
->make('flarum.settings')
->get('custom-prefix.custom_null_setting');
$this->assertEquals(null, $value);
}
}
class CustomInvokableClass