Commit de213bf0 authored by Bas Brands's avatar Bas Brands Committed by Michael Hawkins
Browse files

MDL-64505 theme_classic: Created the classic theme



The Classic theme is being introduced as a Bootstrap 4 replacement
for the older themes based on Bootstrap 2, such as Bootstrapbase,
Clean and More. It is a child theme of Boost, with a navigation
structure similar to the Clean theme.
Co-authored-by: default avatarBas Brands <bmbrands@gmail.com>
Co-authored-by: Michael Hawkins's avatarMichael Hawkins <michaelh@moodle.com>
parent ec819146
......@@ -4,6 +4,7 @@ theme/bootstrapbase/style/
theme/clean/style/custom.css
theme/more/style/custom.css
theme/boost/style/moodle.css
theme/classic/style/moodle.css
node_modules/
vendor/
admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js
......
......@@ -140,11 +140,12 @@ module.exports = function(grunt) {
sass: {
dist: {
files: {
"theme/boost/style/moodle.css": "theme/boost/scss/preset/default.scss"
"theme/boost/style/moodle.css": "theme/boost/scss/preset/default.scss",
"theme/classic/style/moodle.css": "theme/classic/scss/classicgrunt.scss"
}
},
options: {
includePaths: ["theme/boost/scss/"]
includePaths: ["theme/boost/scss/", "theme/classic/scss/"]
}
},
watch: {
......@@ -226,7 +227,8 @@ module.exports = function(grunt) {
'theme/bootstrapbase/style/',
'theme/clean/style/custom.css',
'theme/more/style/custom.css',
'theme/boost/style/moodle.css'
'theme/boost/style/moodle.css',
'theme/classic/style/moodle.css',
].concat(thirdPartyPaths);
grunt.file.write('.stylelintignore', stylelintIgnores.join('\n'));
};
......
......@@ -1905,7 +1905,7 @@ class core_plugin_manager {
),
'theme' => array(
'boost', 'bootstrapbase', 'clean', 'more'
'boost', 'classic', 'bootstrapbase', 'clean', 'more'
),
'tool' => array(
......
<?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/>.
/**
* Renderers to align Moodle's HTML with that expected by Bootstrap
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace theme_classic\output;
defined('MOODLE_INTERNAL') || die;
/**
* Renderers to align Moodle's HTML with that expected by Bootstrap
*
* Note: This class is required to avoid inheriting Boost's core_renderer,
* which removes the edit button required by Classic.
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class core_renderer extends \core_renderer {
}
<?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/>.
/**
* Privacy Subsystem implementation for theme_classic.
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace theme_classic\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* The classic theme does not store any data.
*
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() : string {
return 'privacy:metadata';
}
}
<?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/>.
/**
* classic config.
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// This line protects the file from being accessed by a URL directly.
defined('MOODLE_INTERNAL') || die();
$THEME->name = 'classic';
$THEME->sheets = [];
$THEME->layouts = [
// Most backwards compatible layout without the blocks - this is the layout used by default.
'base' => array(
'file' => 'columns.php',
'regions' => array(),
),
// Standard layout with blocks, this is recommended for most pages with general information.
'standard' => array(
'file' => 'columns.php',
'regions' => array('side-pre', 'side-post'),
'defaultregion' => 'side-pre',
),
// Main course page.
'course' => array(
'file' => 'columns.php',
'regions' => array('side-pre', 'side-post'),
'defaultregion' => 'side-pre',
'options' => array('langmenu' => true),
),
'coursecategory' => array(
'file' => 'columns.php',
'regions' => array('side-pre'),
'defaultregion' => 'side-pre',
),
// Part of course, typical for modules - default page layout if $cm specified in require_login().
'incourse' => array(
'file' => 'columns.php',
'regions' => array('side-pre'),
'defaultregion' => 'side-pre',
),
// The site home page.
'frontpage' => array(
'file' => 'columns.php',
'regions' => array('side-pre', 'side-post'),
'defaultregion' => 'side-pre',
'options' => array('nofullheader' => true),
),
// Server administration scripts.
'admin' => array(
'file' => 'columns.php',
'regions' => array('side-pre'),
'defaultregion' => 'side-pre',
),
// My dashboard page.
'mydashboard' => array(
'file' => 'columns.php',
'regions' => array('side-pre', 'side-post'),
'defaultregion' => 'side-pre',
'options' => array('nonavbar' => true, 'langmenu' => true, 'nocontextheader' => true),
),
// My public page.
'mypublic' => array(
'file' => 'columns.php',
'regions' => array('side-pre'),
'defaultregion' => 'side-pre',
),
'login' => array(
'theme' => 'boost',
'file' => 'login.php',
'regions' => array(),
'options' => array('langmenu' => true),
),
// Pages that appear in pop-up windows - no navigation, no blocks, no header.
'popup' => array(
'file' => 'contentonly.php',
'regions' => array(),
'options' => array('nofooter' => true, 'nonavbar' => true),
),
// No blocks and minimal footer - used for legacy frame layouts only!
'frametop' => array(
'file' => 'contentonly.php',
'regions' => array(),
'options' => array('nofooter' => true, 'nocoursefooter' => true),
),
// Embeded pages, like iframe/object embeded in moodleform - it needs as much space as possible.
'embedded' => array(
'theme' => 'boost',
'file' => 'embedded.php',
'regions' => array()
),
// Used during upgrade and install, and for the 'This site is undergoing maintenance' message.
// This must not have any blocks, links, or API calls that would lead to database or cache interaction.
// Please be extremely careful if you are modifying this layout.
'maintenance' => array(
'theme' => 'boost',
'file' => 'maintenance.php',
'regions' => array(),
),
// Should display the content and basic headers only.
'print' => array(
'file' => 'contentonly.php',
'regions' => array(),
'options' => array('nofooter' => true, 'nonavbar' => false),
),
// The pagelayout used when a redirection is occuring.
'redirect' => array(
'theme' => 'boost',
'file' => 'embedded.php',
'regions' => array(),
),
// The pagelayout used for reports.
'report' => array(
'file' => 'columns.php',
'regions' => array('side-pre'),
'defaultregion' => 'side-pre',
),
// The pagelayout used for safebrowser and securewindow.
'secure' => array(
'file' => 'secure.php',
'regions' => array('side-pre'),
'defaultregion' => 'side-pre'
)
];
$THEME->editor_sheets = [];
$THEME->parents = ['boost'];
$THEME->enable_dock = false;
$THEME->extrascsscallback = 'theme_classic_get_extra_scss';
$THEME->prescsscallback = 'theme_classic_get_pre_scss';
$THEME->precompiledcsscallback = 'theme_classic_get_precompiled_css';
$THEME->yuicssmodules = array();
$THEME->rendererfactory = 'theme_overridden_renderer_factory';
$THEME->scss = function($theme) {
return theme_classic_get_main_scss_content($theme);
};
$THEME->usefallback = true;
<?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/>.
/**
* Language file.
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// This line protects the file from being accessed by a URL directly.
defined('MOODLE_INTERNAL') || die();
// Raw SCSS setting.
$string['choosereadme'] = 'Classic is a highly-customisable theme, based on Boost, with an alternative navigation layout. This theme is intended to be used directly, or as a parent theme when creating or updating custom themes to utilise Bootstrap 4.';
$string['configtitle'] = 'Classic';
$string['navbardark'] = 'Use a dark style navbar';
$string['navbardarkdesc'] = 'Swaps text and background colours for the navbar at the top of the page between dark and light.';
$string['pluginname'] = 'Classic';
$string['presetfiles'] = 'Additional theme preset files';
$string['presetfiles_desc'] = 'Preset files can be used to dramatically alter the appearance of the theme. See <a href=https://docs.moodle.org/dev/Boost_Presets>Boost presets</a> for information on creating and sharing your own preset files, and see the <a href=http://moodle.net/boost>Presets repository</a> for presets that others have shared.';
$string['preset'] = 'Theme preset';
$string['preset_desc'] = 'Pick a preset to broadly change the look of the theme.';
$string['region-side-post'] = 'Right';
$string['region-side-pre'] = 'Left';
$string['sitetitle'] = 'Site Title';
$string['privacy:metadata'] = 'The Classic theme does not store any personal data.';
\ No newline at end of file
<?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/>.
/**
* The columns layout for the classic theme.
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$bodyattributes = $OUTPUT->body_attributes();
$blockspre = $OUTPUT->blocks('side-pre');
$blockspost = $OUTPUT->blocks('side-post');
$hassidepre = $PAGE->blocks->region_has_content('side-pre', $OUTPUT);
$hassidepost = $PAGE->blocks->region_has_content('side-post', $OUTPUT);
$templatecontext = [
'sitename' => format_string($SITE->shortname, true, ['context' => context_course::instance(SITEID), "escape" => false]),
'output' => $OUTPUT,
'sidepreblocks' => $blockspre,
'sidepostblocks' => $blockspost,
'haspreblocks' => $hassidepre,
'haspostblocks' => $hassidepost,
'bodyattributes' => $bodyattributes
];
echo $OUTPUT->render_from_template('theme_classic/columns', $templatecontext);
<?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/>.
/**
* A one column layout for the classic theme.
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$bodyattributes = $OUTPUT->body_attributes([]);
$templatecontext = [
'sitename' => format_string($SITE->shortname, true, ['context' => context_course::instance(SITEID), "escape" => false]),
'output' => $OUTPUT,
'bodyattributes' => $bodyattributes
];
echo $OUTPUT->render_from_template('theme_classic/contentonly', $templatecontext);
<?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/>.
/**
* A secure layout for the classic theme.
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$bodyattributes = $OUTPUT->body_attributes();
$blockspre = $OUTPUT->blocks('side-pre');
$blockspost = $OUTPUT->blocks('side-post');
$hassidepre = $PAGE->blocks->region_has_content('side-pre', $OUTPUT);
$hassidepost = $PAGE->blocks->region_has_content('side-post', $OUTPUT);
$templatecontext = [
'sitename' => format_string($SITE->shortname, true, ['context' => context_course::instance(SITEID), "escape" => false]),
'output' => $OUTPUT,
'sidepreblocks' => $blockspre,
'sidepostblocks' => $blockspost,
'haspreblocks' => $hassidepre,
'haspostblocks' => $hassidepost,
'bodyattributes' => $bodyattributes
];
echo $OUTPUT->render_from_template('theme_classic/secure', $templatecontext);
<?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/>.
/**
* Classic theme callbacks.
*
* @package theme_classic
* @copyright 2018 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// This line protects the file from being accessed by a URL directly.
defined('MOODLE_INTERNAL') || die();
/**
* Returns the main SCSS content.
*
* @param theme_config $theme The theme config object.
* @return string
*/
function theme_classic_get_main_scss_content($theme) {
global $CFG;
$scss = '';
$filename = !empty($theme->settings->preset) ? $theme->settings->preset : null;
$fs = get_file_storage();
$context = context_system::instance();
$scss .= file_get_contents($CFG->dirroot . '/theme/classic/scss/classic/pre.scss');
if ($filename && ($presetfile = $fs->get_file($context->id, 'theme_classic', 'preset', 0, '/', $filename))) {
$scss .= $presetfile->get_content();
} else {
// Safety fallback - maybe new installs etc.
$scss .= file_get_contents($CFG->dirroot . '/theme/classic/scss/preset/default.scss');
}
$scss .= file_get_contents($CFG->dirroot . '/theme/classic/scss/classic/post.scss');
return $scss;
}
/**
* Get SCSS to prepend.
*
* @param theme_config $theme The theme config object.
* @return array
*/
function theme_classic_get_pre_scss($theme) {
$scss = '';
$configurable = [
// Config key => [variableName, ...].
'brandcolor' => ['primary'],
];
// Prepend variables first.
foreach ($configurable as $configkey => $targets) {
$value = isset($theme->settings->{$configkey}) ? $theme->settings->{$configkey} : null;
if (empty($value)) {
continue;
}
array_map(function($target) use (&$scss, $value) {
$scss .= '$' . $target . ': ' . $value . ";\n";
}, (array) $targets);
}
// Prepend pre-scss.
if (!empty($theme->settings->scsspre)) {
$scss .= $theme->settings->scsspre;
}
return $scss;
}
/**
* Inject additional SCSS.
*
* @param theme_config $theme The theme config object.
* @return string
*/
function theme_classic_get_extra_scss($theme) {
global $CFG;
$content = '';
// Set the page background image.
$imageurl = $theme->setting_file_url('backgroundimage', 'backgroundimage');
if (!empty($imageurl)) {
$content .= '$imageurl: "' . $imageurl . '";';
$content .= file_get_contents($CFG->dirroot .
'/theme/classic/scss/classic/body-background.scss');
}
if (!empty($theme->settings->navbardark)) {
$content .= file_get_contents($CFG->dirroot .
'/theme/classic/scss/classic/navbar-dark.scss');
} else {
$content .= file_get_contents($CFG->dirroot .
'/theme/classic/scss/classic/navbar-light.scss');
}
if (!empty($theme->settings->scss)) {
$content .= $theme->settings->scss;
}
return $content;
}
/**
* Get compiled css.
*
* @return string compiled css
*/
function theme_classic_get_precompiled_css() {
global $CFG;
return file_get_contents($CFG->dirroot . '/theme/classic/style/moodle.css');
}
/**
* Serves any files associated with the theme settings.
*
* @param stdClass $course
* @param stdClass $cm
* @param context $context
* @param string $filearea
* @param array $args
* @param bool $forcedownload
* @param array $options
* @return bool
*/
function theme_classic_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) {
if ($context->contextlevel == CONTEXT_SYSTEM && ($filearea === 'backgroundimage')) {
$theme = theme_config::load('classic');
// By default, theme files must be cache-able by both browsers and proxies.
if (!array_key_exists('cacheability', $options)) {
$options['cacheability'] = 'public';
}
return $theme->setting_file_serve($filearea, $args, $forcedownload, $options);
} else {
send_file_not_found();
}
}