Skip to content

Commit

Permalink
feat: Default Settings Extender (#3127)
Browse files Browse the repository at this point in the history
Co-authored-by: Alexander Skvortsov <[email protected]>
  • Loading branch information
SychO9 and askvortsov1 authored Oct 31, 2021
1 parent 7b2adf3 commit fcf23ee
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 5 deletions.
4 changes: 4 additions & 0 deletions src/Database/Migration.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -120,6 +121,9 @@ public static function renameColumns($tableName, array $columnNames)

/**
* 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)
{
Expand Down
32 changes: 31 additions & 1 deletion src/Extend/Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
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.
Expand All @@ -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
Expand All @@ -43,8 +46,35 @@ public function serializeToForum(string $attributeName, string $key, $callback =
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,
Expand Down
47 changes: 47 additions & 0 deletions src/Settings/DefaultSettingsRepository.php
Original file line number Diff line number Diff line change
@@ -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());
}
}
7 changes: 7 additions & 0 deletions src/Settings/SettingsRepositoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
16 changes: 12 additions & 4 deletions src/Settings/SettingsServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Flarum\Foundation\AbstractServiceProvider;
use Illuminate\Contracts\Container\Container;
use Illuminate\Database\ConnectionInterface;
use Illuminate\Support\Collection;

class SettingsServiceProvider extends AbstractServiceProvider
{
Expand All @@ -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')
);
});

Expand Down
57 changes: 57 additions & 0 deletions tests/integration/extenders/SettingsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,63 @@ public function custom_setting_default_passed_to_callback()
$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
Expand Down

0 comments on commit fcf23ee

Please sign in to comment.