Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow mutators for Settings models and improve API #1080

Draft
wants to merge 2 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions modules/system/behaviors/SettingsModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Exception;
use Illuminate\Database\QueryException;
use System\Classes\ModelBehavior;
use Winter\Storm\Database\Model;

/**
* Settings model extension
Expand Down Expand Up @@ -65,7 +66,7 @@ public function __construct($model)
$this->model->bindEvent('model.afterFetch', [$this, 'afterModelFetch']);
$this->model->bindEvent('model.beforeSave', [$this, 'beforeModelSave']);
$this->model->bindEvent('model.afterSave', [$this, 'afterModelSave']);
$this->model->bindEvent('model.setAttribute', [$this, 'setSettingsValue']);
$this->model->bindEvent('model.setAttribute', [$this, 'syncModelAttribute']);
$this->model->bindEvent('model.saveInternal', [$this, 'saveModelInternal']);

/*
Expand All @@ -81,14 +82,15 @@ public function __construct($model)
/**
* Create an instance of the settings model, intended as a static method
*/
public function instance()
public function instance(): Model
{
if (isset(self::$instances[$this->recordCode])) {
return self::$instances[$this->recordCode];
}

if (!$item = $this->getSettingsRecord()) {
$this->model->initSettingsData();
$this->afterModelFetch();
$item = $this->model;
}

Expand Down Expand Up @@ -183,6 +185,14 @@ public function setSettingsValue($key, $value)
$this->fieldValues[$key] = $value;
}

/**
* Sync the provided attribute into the settings value
*/
protected function syncModelAttribute($key)
{
$this->setSettingsValue($key, $this->model->getAttribute($key));
}

/**
* Default values to set for this model, override
*/
Expand Down Expand Up @@ -235,6 +245,8 @@ public function afterModelSave()
} catch (Exception $e) {
Log::warning($e->getMessage());
}

$this->afterModelFetch();
}

/**
Expand Down
133 changes: 133 additions & 0 deletions modules/system/tests/behaviors/SettingsModelTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?php

namespace System\Tests\Behaviors;

use System\Behaviors\SettingsModel;
use System\Tests\Bootstrap\PluginTestCase;
use Winter\Storm\Database\Model;

/**
* @testdox Settings model behavior (System\Behaviors\SettingsModel)
* @author Ben Thomson <git@alfreido.com>
* @copyright Winter CMS Maintainers
*/
class SettingsModelTest extends PluginTestCase
{
public function tearDown(): void
{
MyShopSettings::instance()->resetDefault();
}

public function testCanDetermineIfSettingsModelIsConfigured()
{
$settings = MyShopSettings::instance();

$this->assertFalse($settings->isConfigured());

$settings->name = 'My shop';
$settings->description = 'This is my shop';
$settings->save();

$this->assertTrue($settings->isConfigured());
}

public function testCanInitializeSettingsData()
{
// Configure settings
$settings = MyShopSettings::instance();
$settings->save();

MyShopSettings::clearInternalCache();

// Retrieve settings
$settings = MyShopSettings::instance();
$this->assertEquals('Shop name', $settings->name);
$this->assertEquals('This is a shop', $settings->description);
$this->assertFalse($settings->is_open);
$this->assertEquals(10000, $settings->base_price);
$this->assertEquals(['Food', 'Drinks', 'Clothing', 'Electronics'], $settings->categories);
}

public function testCanGetAndSetSettingsData()
{
$settings = MyShopSettings::instance();

// Set settings as model attributes
$settings->name = 'My shop';
$settings->save();

// Set settings through the set() method
MyShopSettings::set('description', 'This is my shop');
MyShopSettings::set([
'is_open' => true,
'base_price' => 250,
]);
MyShopSettings::set('categories', ['Party Food', 'Party Drinks', 'Party Entertainment']);

// Retrieve settings
$settings = MyShopSettings::instance();

// Retrieve settings through instance
$this->assertEquals('My shop', $settings->name);
$this->assertEquals('This is my shop', $settings->description);

// Retrieve settings through get() method
$this->assertTrue(MyShopSettings::get('is_open'));
$this->assertEquals(25000, MyShopSettings::get('base_price'));
$this->assertEquals(['Party Food', 'Party Drinks', 'Party Entertainment'], MyShopSettings::get('categories'));

// Retrieve default value for a non-existent setting
$this->assertEquals('default', MyShopSettings::get('non_existent_setting', 'default'));
}

/**
* This is similar to the `testCanInitializeSettingsData` test, except that it does not commit the settings to the
* database initially. We should still be able to retrieve the settings defined in `initSettingsData`.
*/
public function testCanGetDefaultSettings()
{
$settings = MyShopSettings::instance();

// Retrieve settings through instance
$this->assertEquals('Shop name', $settings->name);
$this->assertEquals('This is a shop', $settings->description);

// Retrieve settings through get() method
$this->assertFalse(MyShopSettings::get('is_open'));
$this->assertEquals(10000, MyShopSettings::get('base_price'));
$this->assertEquals(['Food', 'Drinks', 'Clothing', 'Electronics'], MyShopSettings::get('categories'));

// Retrieve default value for a non-existent setting
$this->assertEquals('default', MyShopSettings::get('non_existent_setting', 'default'));
}
}

/**
* @mixin \System\Behaviors\SettingsModel
*/
class MyShopSettings extends Model
{
public $implement = [
SettingsModel::class,
];

public $settingsCode = 'my_shop';

public $settingsFields = 'fields.yaml';

public $settingsCacheTtl = 1440;

public function initSettingsData()
{
$this->name = 'Shop name';
$this->description = 'This is a shop';
$this->is_open = false;
$this->base_price = 100;
$this->categories = ['Food', 'Drinks', 'Clothing', 'Electronics'];
}

public function setBasePriceAttribute($value)
{
$this->attributes['base_price'] = $value * 100;
}
}
Loading