diff --git a/CHANGELOG.md b/CHANGELOG.md
index 022a3a4a7..68f1ef2c5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+* **Build 16x** (2014-12-xx)
+ - Settings pages now have a *Reset to default* button.
+ - The field `authorUrl` has been renamed to `homepage` in theme.yaml files.
+ - Adds Theme customization feature (see Themes > Development docs).
+
* **Build 166** (2014-11-27)
- Plugin details method now support "homepage" property (see Plugins > Registration & Versions docs).
- Fixes a bug in the Datepicker using `time` mode.
diff --git a/modules/backend/behaviors/FormController.php b/modules/backend/behaviors/FormController.php
index 7baf680ec..b99e8b8d2 100644
--- a/modules/backend/behaviors/FormController.php
+++ b/modules/backend/behaviors/FormController.php
@@ -222,7 +222,7 @@ class FormController extends ControllerBehavior
$this->controller->formBeforeSave($model);
$this->controller->formBeforeUpdate($model);
- $modelsToSave =$this->prepareModelsToSave($model, $this->formWidget->getSaveData());
+ $modelsToSave = $this->prepareModelsToSave($model, $this->formWidget->getSaveData());
foreach ($modelsToSave as $modelToSave) {
$modelToSave->save(null, $this->formWidget->getSessionKey());
}
diff --git a/modules/backend/lang/en/lang.php b/modules/backend/lang/en/lang.php
index 31a5c4bfe..62003697e 100644
--- a/modules/backend/lang/en/lang.php
+++ b/modules/backend/lang/en/lang.php
@@ -155,6 +155,9 @@ return [
'delete' => 'Delete',
'deleting' => 'Deleting...',
'deleting_name' => 'Deleting :name...',
+ 'reset_default' => 'Reset to default',
+ 'resetting' => 'Resetting',
+ 'resetting_name' => 'Resetting :name',
'undefined_tab' => 'Misc',
'field_off' => 'Off',
'field_on' => 'On',
diff --git a/modules/cms/classes/Theme.php b/modules/cms/classes/Theme.php
index 2b9050674..f4c321006 100644
--- a/modules/cms/classes/Theme.php
+++ b/modules/cms/classes/Theme.php
@@ -257,12 +257,7 @@ class Theme
*/
public function getConfigValue($name, $default = null)
{
- $config = $this->getConfig();
- if (isset($config[$name])) {
- return $config[$name];
- }
-
- return $default;
+ return array_get($this->getConfig(), $name, $default);
}
/**
diff --git a/modules/cms/controllers/Themes.php b/modules/cms/controllers/Themes.php
index 736d5fefa..657783ce9 100644
--- a/modules/cms/controllers/Themes.php
+++ b/modules/cms/controllers/Themes.php
@@ -1,11 +1,16 @@
bodyClass = 'compact-container';
}
public function index_onSetActiveTheme()
@@ -46,4 +56,67 @@ class Themes extends Controller
'#theme-list' => $this->makePartial('theme_list')
];
}
+
+ //
+ // Theme customization
+ //
+
+ public function update($dirName)
+ {
+ try {
+ $model = $this->getThemeData($dirName);
+ $this->asExtension('FormController')->update($model->id);
+ }
+ catch (Exception $ex) {
+ $this->handleError($ex);
+ }
+ }
+
+ public function update_onSave($dirName)
+ {
+ $model = $this->getThemeData($dirName);
+ $this->asExtension('FormController')->update_onSave($model->id);
+ }
+
+ public function update_onResetDefault($dirName)
+ {
+ $model = $this->getThemeData($dirName);
+ $model->delete();
+
+ $redirectUrl = Backend::url('cms/themes/update/'.$dirName);
+ return Redirect::to($redirectUrl);
+ }
+
+ protected function getThemeData($dirName)
+ {
+ if (!$theme = CmsTheme::load($dirName))
+ throw new Exception(Lang::get('Unable to find theme with name :name', $dirName));
+
+ $model = ThemeData::firstOrCreate(['theme' => $theme->getDirName()]);
+ return $model;
+ }
+
+ /**
+ * Add form fields defined in theme.yaml
+ */
+ protected function formExtendFields($form)
+ {
+ $model = $form->model;
+
+ if (!$theme = CmsTheme::load($model->theme))
+ throw new Exception(Lang::get('Unable to find theme with name :name', $dirName));
+
+ if ($fields = $theme->getConfigValue('form.fields')) {
+ $form->addFields($fields);
+ }
+
+ if ($fields = $theme->getConfigValue('form.tabs.fields')) {
+ $form->addTabFields($fields);
+ }
+
+ if ($fields = $theme->getConfigValue('form.secondaryTabs.fields')) {
+ $form->addSecondaryTabFields($fields);
+ }
+ }
+
}
diff --git a/modules/cms/controllers/themes/_theme_list.htm b/modules/cms/controllers/themes/_theme_list.htm
index 66070e94e..a63b6221c 100644
--- a/modules/cms/controllers/themes/_theme_list.htm
+++ b/modules/cms/controllers/themes/_theme_list.htm
@@ -7,6 +7,7 @@
getDirName() == $theme->getDirName();
+ $hasForm = $theme->getConfigValue('form');
$author = $theme->getConfigValue('author');
?>
@@ -16,7 +17,7 @@
= e($theme->getConfigValue('name', $theme->getDirName())) ?>
-
by = e($author) ?>
+
by = e($author) ?>
= e($theme->getConfigValue('description', 'The theme description is not provided.')) ?>
diff --git a/modules/cms/controllers/themes/config_form.yaml b/modules/cms/controllers/themes/config_form.yaml
new file mode 100644
index 000000000..ac372ee83
--- /dev/null
+++ b/modules/cms/controllers/themes/config_form.yaml
@@ -0,0 +1,21 @@
+# ===================================
+# Form Behavior Config
+# ===================================
+
+# Record name
+name: Theme
+
+# Fields are defined by extension
+form: []
+
+# Model Class name
+modelClass: Cms\Models\ThemeData
+
+# Default redirect location
+defaultRedirect: cms/themes
+
+# Update page
+update:
+ title: Customize Theme
+ redirect: cms/themes
+ redirectClose: cms/themes
diff --git a/modules/cms/controllers/themes/update.htm b/modules/cms/controllers/themes/update.htm
new file mode 100644
index 000000000..104ad9e44
--- /dev/null
+++ b/modules/cms/controllers/themes/update.htm
@@ -0,0 +1,59 @@
+
+
+ - Themes
+ - = e(trans($this->pageTitle)) ?>
+
+
+
+fatalError): ?>
+
+ = Form::open(['class'=>'layout']) ?>
+
+
+ = $this->formRender() ?>
+
+
+
+
+ = Form::close() ?>
+
+
+
+ = e($this->fatalError) ?>
+ Return to themes list
+
+
\ No newline at end of file
diff --git a/modules/cms/database/migrations/.gitkeep b/modules/cms/database/migrations/.gitkeep
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modules/cms/database/migrations/2014_10_01_000001_Db_Cms_Theme_Data.php b/modules/cms/database/migrations/2014_10_01_000001_Db_Cms_Theme_Data.php
new file mode 100644
index 000000000..574974f9c
--- /dev/null
+++ b/modules/cms/database/migrations/2014_10_01_000001_Db_Cms_Theme_Data.php
@@ -0,0 +1,23 @@
+engine = 'InnoDB';
+ $table->increments('id');
+ $table->string('theme')->nullable()->index();
+ $table->mediumtext('data')->nullable();
+ $table->timestamps();
+ });
+ }
+
+ public function down()
+ {
+ Schema::dropIfExists('cms_theme_data');
+ }
+}
diff --git a/modules/cms/lang/en/lang.php b/modules/cms/lang/en/lang.php
index 443711c9f..3ead1ede9 100644
--- a/modules/cms/lang/en/lang.php
+++ b/modules/cms/lang/en/lang.php
@@ -27,6 +27,7 @@ return [
'find_more_themes' => 'Find more themes on OctoberCMS Theme Marketplace.',
'activate_button' => 'Activate',
'active_button' => 'Activate',
+ 'customize_button' => 'Customize',
],
'maintenance' => [
'settings_menu' => 'Maintenance mode',
diff --git a/modules/cms/models/ThemeData.php b/modules/cms/models/ThemeData.php
new file mode 100644
index 000000000..e307bb363
--- /dev/null
+++ b/modules/cms/models/ThemeData.php
@@ -0,0 +1,54 @@
+getAttributes(), $staticAttributes);
+
+ $this->data = $dynamicAttributes;
+ $this->setRawAttributes(array_only($this->getAttributes(), $staticAttributes));
+ }
+
+ public function afterFetch()
+ {
+ /*
+ * Fill this model with the jsonable attributes kept in 'data'.
+ */
+ $this->setRawAttributes((array) $this->getAttributes() + (array) $this->data, true);
+ }
+}
diff --git a/modules/system/behaviors/SettingsModel.php b/modules/system/behaviors/SettingsModel.php
index f676f15fa..8b22a8b4c 100644
--- a/modules/system/behaviors/SettingsModel.php
+++ b/modules/system/behaviors/SettingsModel.php
@@ -83,6 +83,18 @@ class SettingsModel extends ModelBehavior
return self::$instances[$this->recordCode] = $item;
}
+ /**
+ * Reset the settings to their defaults, this will delete the record model
+ */
+ public function resetDefault()
+ {
+ if ($record = $this->getSettingsRecord()) {
+ $record->delete();
+ unset(self::$instances[$this->recordCode]);
+ Cache::forget($this->getCacheKey());
+ }
+ }
+
/**
* Checks if the model has been set up previously, intended as a static method
*/
diff --git a/modules/system/controllers/Settings.php b/modules/system/controllers/Settings.php
index 36e808e76..334baf07f 100644
--- a/modules/system/controllers/Settings.php
+++ b/modules/system/controllers/Settings.php
@@ -111,6 +111,16 @@ class Settings extends Controller
}
}
+ public function update_onResetDefault($author, $plugin, $code = null)
+ {
+ $item = $this->findSettingItem($author, $plugin, $code);
+ $model = $this->createModel($item);
+ $model->resetDefault();
+
+ $redirectUrl = Backend::url('system/settings/update/'.$author.'/'.$plugin.'/'.$code);
+ return Redirect::to($redirectUrl);
+ }
+
/**
* Render the form.
*/
diff --git a/modules/system/controllers/settings/update.htm b/modules/system/controllers/settings/update.htm
index 95bcd9ce5..65ae3b683 100644
--- a/modules/system/controllers/settings/update.htm
+++ b/modules/system/controllers/settings/update.htm
@@ -29,6 +29,15 @@
= e(trans('backend::lang.form.or')) ?> = e(trans('backend::lang.form.cancel')) ?>
+
+
= Form::close() ?>