MDL-55384 theme_noname: Admin settings to customise the theme
authorFrederic Massart <fred@moodle.com>
Tue, 2 Aug 2016 08:30:37 +0000 (16:30 +0800)
committerDan Poltawski <dan@moodle.com>
Fri, 23 Sep 2016 09:53:30 +0000 (10:53 +0100)
Part of MDL-55071

theme/noname/classes/admin_setting_scss_variables.php [new file with mode: 0644]
theme/noname/config.php
theme/noname/lang/en/theme_noname.php
theme/noname/lib.php
theme/noname/scss/preset-default.scss [new file with mode: 0644]
theme/noname/settings.php
theme/noname/version.php

diff --git a/theme/noname/classes/admin_setting_scss_variables.php b/theme/noname/classes/admin_setting_scss_variables.php
new file mode 100644 (file)
index 0000000..b23e877
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Admin setting for SCSS variables.
+ *
+ * @package   theme_noname
+ * @copyright 2016 Frédéric Massart - FMCorz.net
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Admin setting for SCSS variables class.
+ *
+ * @package   theme_noname
+ * @copyright 2016 Frédéric Massart - FMCorz.net
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class theme_noname_admin_setting_scss_variables extends admin_setting_configtextarea {
+
+    /**
+     * Validate data before storage.
+     *
+     * @param string $data The data.
+     * @return mixed True if validated, else an error string.
+     */
+    public function validate($data) {
+        if (empty($data)) {
+            return true;
+        }
+
+        try {
+            theme_noname_parse_scss_variables($data, false);
+        } catch (moodle_exception $e) {
+            return $e->getMessage();
+        }
+
+        return true;
+    }
+
+}
+
index 738ac9e..25d1474 100644 (file)
 
 defined('MOODLE_INTERNAL') || die();
 
+require_once(__DIR__ . '/lib.php');
+
 $THEME->name = 'noname';
-$THEME->scssfile = 'moodle';
+$THEME->scssfile = theme_noname_get_scss_file($THEME);
 $THEME->sheets = [];
 $THEME->editor_sheets = ['editor'];
 
@@ -145,6 +147,8 @@ $THEME->layouts = [
 $THEME->parents = [];
 $THEME->enable_dock = false;
 $THEME->csstreepostprocessor = 'theme_noname_css_tree_post_processor';
+$THEME->extrascsscallback = 'theme_noname_get_extra_scss';
+$THEME->scssvariablescallback = 'theme_noname_get_scss_variables';
 $THEME->supportscssoptimisation = false;
 $THEME->yuicssmodules = array();
 $THEME->rendererfactory = 'theme_overridden_renderer_factory';
index d380f3d..3b10029 100644 (file)
 
 defined('MOODLE_INTERNAL') || die();
 
+$string['advancedsettings'] = 'Advanced settings';
+$string['brandcolor'] = 'Brand colour';
+$string['brandcolor_desc'] = 'The accent colour.';
 $string['choosereadme'] = 'Hey, change me!';
 $string['currentinparentheses'] = '(current)';
+$string['configtitle'] = 'CHANGE ME!';
+$string['errorparsingscssvariables'] = 'There was an error parsing the variable at line {$a}, please double check the syntax.';
+$string['generalsettings'] = 'General settings';
 $string['pluginname'] = 'NONAME';
+$string['preset'] = 'Theme preset';
+$string['preset_desc'] = 'Pick a preset to broadly change the look of the theme.';
+$string['presetdefault'] = 'Default';
+$string['rawscss'] = 'Raw SCSS';
+$string['rawscss_desc'] = 'Use this field to provide SCSS code which will be injected at the end of the the stylesheet.';
 $string['region-side-post'] = 'Right';
 $string['region-side-pre'] = 'Left';
+$string['scssvariables'] = 'SCSS variables';
+$string['scssvariables_desc'] = 'Use this field to set your own SCSS variable values. Define one variable per line. Syntax: $my-color: red;.';
index 47dd00f..f0ed6c3 100644 (file)
@@ -34,3 +34,96 @@ function theme_noname_css_tree_post_processor($tree, $this) {
     $prefixer = new theme_noname\autoprefixer($tree);
     $prefixer->prefix();
 }
+
+/**
+ * Get the SCSS file to include.
+ *
+ * @param theme_config $theme The theme config object.
+ * @return string The name of the file without 'scss'.
+ */
+function theme_noname_get_scss_file($theme) {
+    $preset = !empty($theme->settings->preset) ? $theme->settings->preset : 'default';
+    return 'preset-' . $preset;
+}
+
+/**
+ * Inject additional SCSS.
+ *
+ * @param theme_config $theme The theme config object.
+ * @return string
+ */
+function theme_noname_get_extra_scss($theme) {
+    return !empty($theme->settings->scss) ? $theme->settings->scss : '';
+}
+
+/**
+ * Get additional SCSS variables.
+ *
+ * @param theme_config $theme The theme config object.
+ * @return array
+ */
+function theme_noname_get_scss_variables($theme) {
+    $variables = [];
+    $configurable = [
+        // Config key => [variableName, ...].
+        'brandcolor' => ['brand-primary'],
+    ];
+
+    foreach ($configurable as $configkey => $targets) {
+        $value = $theme->settings->{$configkey};
+        if (empty($value)) {
+            continue;
+        }
+        array_map(function($target) use (&$variables, $value) {
+            $variables[$target] = $value;
+        }, (array) $targets);
+    }
+
+    if (!empty($theme->settings->scss_variables)) {
+        $variables = array_merge($variables, theme_noname_parse_scss_variables($theme->settings->scss_variables));
+    }
+
+    return $variables;
+}
+
+/**
+ * Parse a string into SCSS variables.
+ *
+ * - One variable definition per line,
+ * - The variable name is separated from the value by a colon,
+ * - The dollar sign is optional,
+ * - The trailing semi-colon is optional,
+ * - CSS comments (starting with //) are accepted
+ * - Variables names can only contain letters, numbers, hyphens and underscores.
+ *
+ * @param string $data The string to parse from.
+ * @param bool $lenient When non lenient, an exception will be thrown when a line cannot be parsed.
+ * @return array
+ */
+function theme_noname_parse_scss_variables($data, $lenient = true) {
+    $variables = [];
+    $lines = explode("\n", $data);
+    $i = 0;
+
+    foreach ($lines as $line) {
+        $i++;
+        if (preg_match('@^\s*//@', $line)) {
+            continue;
+        }
+
+        $parts = explode(':', trim($line));
+        $variable = ltrim($parts[0], '$ ');
+        $value = rtrim(ltrim(isset($parts[1]) ? $parts[1] : ''), "; ");
+
+        if (empty($variable) || !preg_match('/^[a-z0-9_-]+$/i', $variable) || (empty($value) && !is_numeric($value))) {
+            if ($lenient) {
+                continue;
+            }
+            throw new moodle_exception('errorparsingscssvariables', 'theme_noname', null, $i);
+        }
+
+        $variables[$variable] = $value;
+    }
+
+    return $variables;
+}
diff --git a/theme/noname/scss/preset-default.scss b/theme/noname/scss/preset-default.scss
new file mode 100644 (file)
index 0000000..309abe4
--- /dev/null
@@ -0,0 +1,12 @@
+/**
+ * Default preset file.
+ *
+ * Use this space to customise variables, create mixins and override SCSS.
+ */
+
+// Variables and mixins here. Do not forget to make your variable defaults.
+
+// Import everything.
+@import "moodle";
+
+// Additional scss here.
index 15dc504..86c2ebd 100644 (file)
 defined('MOODLE_INTERNAL') || die();
 
 if ($ADMIN->fulltree) {
+    $settings = new theme_noname_admin_settingspage_tabs('themesettingnoname', get_string('configtitle', 'theme_noname'));
+    $page = new admin_settingpage('theme_noname_general', get_string('generalsettings', 'theme_noname'));
 
-    $settings = new theme_noname_admin_settingspage_tabs('theme_noname', 'CONFIG TITLE');
-    $temp = new admin_settingpage('theme_noname_general',  'GENERAL SETTINGS');
+    // Preset.
+    $name = 'theme_noname/preset';
+    $title = get_string('preset', 'theme_noname');
+    $description = get_string('preset_desc', 'theme_noname');
+    $choices = [
+        // A file named 'preset-' . key . '.scss' is expected.
+        'default' => get_string('presetdefault', 'theme_noname')
+    ];
+    $default = 'default';
+    $setting = new admin_setting_configselect($name, $title, $description, $default, $choices);
+    $setting->set_updatedcallback('theme_reset_all_caches');
+    $page->add($setting);
 
-    $settings->add($temp);
-    $temp = new admin_settingpage('theme_noname_advanced',  'ADVANCED');
+    // Variable $body-color.
+    $name = 'theme_noname/brandcolor';
+    $title = get_string('brandcolor', 'theme_noname');
+    $description = get_string('brandcolor_desc', 'theme_noname');
+    $default = '#373A3C';   // Straight from bootstrap variables.
+    $setting = new admin_setting_configcolourpicker($name, $title, $description, $default, null, false);
+    $setting->set_updatedcallback('theme_reset_all_caches');
+    $page->add($setting);
 
-    $settings->add($temp);
+    // Must add the page after definiting all the settings!
+    $settings->add($page);
+
+    // Advanced settings.
+    $page = new admin_settingpage('theme_noname_advanced', get_string('advancedsettings', 'theme_noname'));
+
+    // Raw SCSS for before the content.
+    $setting = new theme_noname_admin_setting_scss_variables('theme_noname/scss_variables',
+        get_string('scssvariables', 'theme_noname'), get_string('scssvariables_desc', 'theme_noname'), '', PARAM_RAW);
+    $setting->set_updatedcallback('theme_reset_all_caches');
+    $page->add($setting);
+
+    // Raw SCSS for after the content.
+    $setting = new admin_setting_configtextarea('theme_noname/scss', get_string('rawscss', 'theme_noname'),
+        get_string('rawscss_desc', 'theme_noname'), '', PARAM_RAW);
+    $setting->set_updatedcallback('theme_reset_all_caches');
+    $page->add($setting);
+
+    $settings->add($page);
 }
index bcfd450..92a2080 100644 (file)
@@ -24,7 +24,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016071100;
+$plugin->version   = 2016071101;
 $plugin->requires  = 2016070700;
 $plugin->component = 'theme_noname';
 $plugin->release   = '1.0';