Add new settings service
[MAILPOET-1757]
This commit is contained in:
@ -74,6 +74,8 @@ class ContainerConfigurator implements IContainerConfigurator {
|
||||
$container->autowire(\MailPoet\Subscribers\RequiredCustomFieldValidator::class)->setPublic(true);
|
||||
// Segments
|
||||
$container->autowire(\MailPoet\Segments\SubscribersListings::class)->setPublic(true);
|
||||
// Settings
|
||||
$container->autowire(\MailPoet\Settings\SettingsController::class)->setPublic(true);
|
||||
// Subscription
|
||||
$container->autowire(\MailPoet\Subscription\Form::class)->setPublic(true);
|
||||
// Newsletter
|
||||
|
104
lib/Settings/SettingsController.php
Normal file
104
lib/Settings/SettingsController.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
namespace MailPoet\Settings;
|
||||
|
||||
use Composer\Package\Package;
|
||||
use MailPoet\Models\Setting;
|
||||
|
||||
class SettingsController {
|
||||
private static $loaded = false;
|
||||
|
||||
private static $settings = [];
|
||||
|
||||
function get($key, $default = null) {
|
||||
$this->ensureLoaded();
|
||||
$keys = explode('.', $key);
|
||||
$setting = self::$settings;
|
||||
if($default === null) {
|
||||
$default = $this->getDefault($keys);
|
||||
}
|
||||
foreach($keys as $key) {
|
||||
if(array_key_exists($key, $setting)) {
|
||||
$setting = $setting[$key];
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
if(is_array($setting) && is_array($default)) {
|
||||
return array_replace_recursive($default, $setting);
|
||||
}
|
||||
return $setting;
|
||||
}
|
||||
|
||||
function getDefaults() {
|
||||
return Setting::getDefaults();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the value from DB and update in cache
|
||||
* This is required for sync settings between parallel processes e.g. cron
|
||||
*/
|
||||
function fetch($key, $default = null) {
|
||||
$keys = explode('.', $key);
|
||||
$main_key = $keys[0];
|
||||
self::$settings[$main_key] = Setting::getValue($main_key);
|
||||
return $this->get($key, $default);
|
||||
}
|
||||
|
||||
function getAll() {
|
||||
$this->ensureLoaded();
|
||||
return self::$settings;
|
||||
}
|
||||
|
||||
function set($key, $value) {
|
||||
$this->ensureLoaded();
|
||||
$keys = explode('.', $key);
|
||||
$main_key = $keys[0];
|
||||
$last_key = array_pop($keys);
|
||||
$settings = self::$settings;
|
||||
$setting =& $settings;
|
||||
foreach($keys as $key) {
|
||||
$setting =& $setting[$key];
|
||||
if(!is_array($setting)) {
|
||||
$setting = [];
|
||||
}
|
||||
}
|
||||
$setting[$last_key] = $value;
|
||||
Setting::setValue($main_key, $settings[$main_key]);
|
||||
self::$settings = $settings;
|
||||
}
|
||||
|
||||
function delete($key) {
|
||||
Setting::deleteValue($key);
|
||||
unset(self::$settings[$key]);
|
||||
}
|
||||
|
||||
private function ensureLoaded() {
|
||||
if(self::$loaded) {
|
||||
return;
|
||||
}
|
||||
self::$settings = Setting::getAll() ?: [];
|
||||
self::$loaded = true;
|
||||
}
|
||||
|
||||
private function getDefault($keys) {
|
||||
$default = $this->getDefaults();
|
||||
foreach($keys as $key) {
|
||||
if(array_key_exists($key, $default)) {
|
||||
$default = $default[$key];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary function for tests use only.
|
||||
* It is needed until this is only instantiated in one place (DI Container)
|
||||
* Once this is achieved we can make properties not static and remove this method
|
||||
*/
|
||||
static function resetCache() {
|
||||
self::$settings = [];
|
||||
self::$loaded = false;
|
||||
}
|
||||
}
|
103
tests/integration/Settings/SettingsControllerTest.php
Normal file
103
tests/integration/Settings/SettingsControllerTest.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
namespace MailPoet\Test\Settings;
|
||||
|
||||
use Codeception\Stub;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Settings\SettingsController;
|
||||
|
||||
class SettingsControllerTest extends \MailPoetTest {
|
||||
|
||||
/** @var SettingsController */
|
||||
private $controller;
|
||||
|
||||
function _before() {
|
||||
$this->controller = new SettingsController();
|
||||
}
|
||||
|
||||
function testItReturnsStoredValue() {
|
||||
Setting::setValue('test_key', 1);
|
||||
$this->assertEquals(1, $this->controller->get('test_key'));
|
||||
}
|
||||
|
||||
function testItReturnsStoredNestedValue() {
|
||||
Setting::setValue('test_key', ['sub_key' => 'value']);
|
||||
$this->assertEquals('value', $this->controller->get('test_key.sub_key'));
|
||||
}
|
||||
|
||||
function testItReturnsNullForUnknownSetting() {
|
||||
$this->assertEquals(null, $this->controller->get('test_key'));
|
||||
$this->assertEquals(null, $this->controller->get('test_key.sub_key'));
|
||||
Setting::setValue('test_key', ['sub_key' => 'value']);
|
||||
$this->assertEquals(null, $this->controller->get('test_key.wrong_subkey'));
|
||||
}
|
||||
|
||||
function testItReturnsDefaultValueForUnknownSetting() {
|
||||
$this->assertEquals('default', $this->controller->get('test_key', 'default'));
|
||||
$this->assertEquals('default', $this->controller->get('test_key.sub_key', 'default'));
|
||||
Setting::setValue('test_key', ['sub_key' => 'value']);
|
||||
$this->assertEquals('default', $this->controller->get('test_key.wrong_subkey', 'default'));
|
||||
}
|
||||
|
||||
function testItReturnsDefaultValueAsFallback() {
|
||||
$settings = Stub::make($this->controller, [
|
||||
'getDefaults' => function () {
|
||||
return ['default1' => ['default2' => 1]];
|
||||
}
|
||||
]);
|
||||
$settings->delete('default1');
|
||||
$value = $settings->get('default1');
|
||||
$this->assertEquals(1, $value['default2']);
|
||||
$this->assertEquals(1, $settings->get('default1.default2'));
|
||||
}
|
||||
|
||||
function testItCanReturnAllSettings() {
|
||||
Setting::setValue('test_key1', 1);
|
||||
Setting::setValue('test_key2', 2);
|
||||
$all = $this->controller->getAll();
|
||||
$this->assertEquals(1, $all['test_key1']);
|
||||
$this->assertEquals(2, $all['test_key2']);
|
||||
}
|
||||
|
||||
function testItCanSetAtTopLevel() {
|
||||
$this->controller->set('test_key', 1);
|
||||
$this->assertEquals(1, $this->controller->get('test_key'));
|
||||
$db_value = Setting::getValue('test_key');
|
||||
$this->assertEquals(1, $db_value);
|
||||
}
|
||||
|
||||
function testItCanSetAtNestedLevel() {
|
||||
$this->controller->set('test_key.key1.key2', 1);
|
||||
$this->assertEquals(1, $this->controller->get('test_key.key1.key2'));
|
||||
$db_value = Setting::getValue('test_key');
|
||||
$this->assertEquals(1, $db_value['key1']['key2']);
|
||||
}
|
||||
|
||||
function testItCanSetNUll() {
|
||||
$this->controller->set('test_key.key1.key2', 1);
|
||||
$this->assertEquals(1, $this->controller->get('test_key.key1.key2'));
|
||||
$this->controller->set('test_key.key1.key2', null);
|
||||
$this->assertNull(null, $this->controller->get('test_key.key1.key2'));
|
||||
$db_value = Setting::getValue('test_key');
|
||||
$this->assertNull($db_value['key1']['key2']);
|
||||
}
|
||||
|
||||
function testItCanOverrideValueAndSetAtNestedLevel() {
|
||||
$this->controller->set('test_key.key1', 1);
|
||||
$this->controller->set('test_key.key1.key2', 1);
|
||||
$this->assertEquals(1, $this->controller->get('test_key.key1.key2'));
|
||||
$db_value = Setting::getValue('test_key');
|
||||
$this->assertEquals(1, $db_value['key1']['key2']);
|
||||
}
|
||||
|
||||
function testItLoadsFromDbOnlyOnce() {
|
||||
Setting::setValue('test_key', 1);
|
||||
$this->assertEquals(1, $this->controller->get('test_key'));
|
||||
Setting::setValue('test_key', 2);
|
||||
$this->assertEquals(1, $this->controller->get('test_key'));
|
||||
$this->assertEquals(true, true);
|
||||
}
|
||||
|
||||
function _after() {
|
||||
\ORM::raw_execute('TRUNCATE ' . Setting::$_table);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user