<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Meeth</id>
	<title>MoodleDocs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Meeth"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Meeth"/>
	<updated>2026-08-12T16:02:48Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Creating_a_theme_based_on_boost&amp;diff=57740</id>
		<title>Creating a theme based on boost</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Creating_a_theme_based_on_boost&amp;diff=57740"/>
		<updated>2020-07-31T11:42:23Z</updated>

		<summary type="html">&lt;p&gt;Meeth: Undo revision 57736 by Meeth (talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 3.2}}&lt;br /&gt;
{{Template:Themes}}&lt;br /&gt;
&lt;br /&gt;
This is a tutorial for how to create a new theme in any version of Moodle from 3.2 and later.&lt;br /&gt;
&lt;br /&gt;
Moodle 3.2 introduced a new core theme named &amp;quot;Boost&amp;quot; which is a great starting point for themers wanting to build a modern Moodle theme utilising all the latest features available to themes in Moodle.  If you aren&#039;t sure where to start, then START HERE!  :-)&lt;br /&gt;
&lt;br /&gt;
== Getting started ==&lt;br /&gt;
What is a theme? A theme in Moodle is just another type of plugin that can be developed. Themes are responsible for setting up the structure of each page and have the ability to customise the output of any page in Moodle.&lt;br /&gt;
&lt;br /&gt;
This tutorial is based on a working theme named &amp;quot;theme_photo&amp;quot; you can download it or view the source code for it here: https://github.com/damyon/moodle-theme_photo&lt;br /&gt;
&lt;br /&gt;
=== Choosing a name ===&lt;br /&gt;
Your new theme will need a name. Try and think of something short and memorable - and make sure it is not a name that has already been used by someone else. A quick search on the moodle.org/plugins can save you a lot of work renaming things later.&lt;br /&gt;
&lt;br /&gt;
Lets call our new example theme &amp;quot;photo&amp;quot; as we will add some settings to allow &amp;quot;photos&amp;quot; in various places in Moodle.&lt;br /&gt;
&lt;br /&gt;
=== Starting files ===&lt;br /&gt;
As a plugin, themes must start with the basic structure of a plugin in Moodle. See https://docs.moodle.org/dev/Tutorial#The_skeleton_of_your_plugin for an overview of the files common to all plugins in Moodle.&lt;br /&gt;
&lt;br /&gt;
Following this guide we can start creating our theme. First we create the folder for the new theme under &amp;quot;/theme/&amp;quot; folder in the Moodle root directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
/theme/photo/&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we need to add some standard plugin files to our theme. First is version.php&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/theme/photo/version.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the version of the plugin.                                                                                               &lt;br /&gt;
$plugin-&amp;gt;version = &#039;2016102100&#039;;                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the version of Moodle this plugin requires.                                                                              &lt;br /&gt;
$plugin-&amp;gt;requires = &#039;2016070700&#039;;                                                                                                   &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the component name of the plugin - it always starts with &#039;theme_&#039;                                                        &lt;br /&gt;
// for themes and should be the same as the name of the folder.                                                                     &lt;br /&gt;
$plugin-&amp;gt;component = &#039;theme_photo&#039;;                                                                                                 &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a list of plugins, this plugin depends on (and their versions).                                                          &lt;br /&gt;
$plugin-&amp;gt;dependencies = [                                                                                                           &lt;br /&gt;
    &#039;theme_boost&#039; =&amp;gt; &#039;2016102100&#039;                                                                                                   &lt;br /&gt;
];                                                                              &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need a language file so that all our strings can be translated into different languages. The name of this file is the component name of our plugin and it sits in the lang/en/ folder for our plugin. We can include translations of our plugin, but we can also provide translations via the https://lang.moodle.org/ website once our plugin has been published to the plugins database at http://www.moodle.org/plugins/.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/theme/photo/lang/en/theme_photo.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// A description shown in the admin theme selector.                                                                                 &lt;br /&gt;
$string[&#039;choosereadme&#039;] = &#039;Theme photo is a child theme of Boost. It adds the ability to upload background photos.&#039;;                &lt;br /&gt;
// The name of our plugin.                                                                                                          &lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Photo&#039;;                                                                                                    &lt;br /&gt;
// We need to include a lang string for each block region.                                                                          &lt;br /&gt;
$string[&#039;region-side-pre&#039;] = &#039;Right&#039;;                                         &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Theme specific files ===&lt;br /&gt;
Theme plugins have a few more standard files they need to define. &lt;br /&gt;
&lt;br /&gt;
Themes require a favicon file to show in the address bar. See [[http://docs.moodle.org/en/Favicon Favicon]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;pix/favicon.ico&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(Image file not shown).&lt;br /&gt;
&lt;br /&gt;
Themes also require an example screenshot to be displayed in the theme selector.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;pix/screenshot.jpg&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(Image file not shown).&lt;br /&gt;
&lt;br /&gt;
Themes require a lib.php file. This file contains callbacks used by various API&#039;s in Moodle. Initially this file can be empty, but as we add features to our theme we will need to add some functions here.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
// We will add callbacks here as we add features to our theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Theme config goes in a config.php file. This is one of the most important files in our theme. Once we add this file we will be ready to test our theme for the first time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
// $THEME is defined before this page is included and we can define settings by adding properties to this global object.            &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// The first setting we need is the name of the theme. This should be the last part of the component name, and the same             &lt;br /&gt;
// as the directory name for our theme.                                                                                             &lt;br /&gt;
$THEME-&amp;gt;name = &#039;photo&#039;;                                                                                                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This setting list the style sheets we want to include in our theme. Because we want to use SCSS instead of CSS - we won&#039;t        &lt;br /&gt;
// list any style sheets. If we did we would list the name of a file in the /style/ folder for our theme without any css file      &lt;br /&gt;
// extensions.                                                                                                                      &lt;br /&gt;
$THEME-&amp;gt;sheets = [];                                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a setting that can be used to provide some styling to the content in the TinyMCE text editor. This is no longer the      &lt;br /&gt;
// default text editor and &amp;quot;Atto&amp;quot; does not need this setting so we won&#039;t provide anything. If we did it would work the same         &lt;br /&gt;
// as the previous setting - listing a file in the /styles/ folder.                                                                 &lt;br /&gt;
$THEME-&amp;gt;editor_sheets = [];                                                                                                         &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a critical setting. We want to inherit from theme_boost because it provides a great starting point for SCSS bootstrap4   &lt;br /&gt;
// themes. We could add more than one parent here to inherit from multiple parents, and if we did they would be processed in        &lt;br /&gt;
// order of importance (later themes overriding earlier ones). Things we will inherit from the parent theme include                 &lt;br /&gt;
// styles and mustache templates and some (not all) settings.                                                                       &lt;br /&gt;
$THEME-&amp;gt;parents = [&#039;boost&#039;];                                                                                                        &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// A dock is a way to take blocks out of the page and put them in a persistent floating area on the side of the page. Boost         &lt;br /&gt;
// does not support a dock so we won&#039;t either - but look at bootstrapbase for an example of a theme with a dock.                    &lt;br /&gt;
$THEME-&amp;gt;enable_dock = false;                                                                                                        &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is an old setting used to load specific CSS for some YUI JS. We don&#039;t need it in Boost based themes because Boost           &lt;br /&gt;
// provides default styling for the YUI modules that we use. It is not recommended to use this setting anymore.                     &lt;br /&gt;
$THEME-&amp;gt;yuicssmodules = array();                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// Most themes will use this rendererfactory as this is the one that allows the theme to override any other renderer.               &lt;br /&gt;
$THEME-&amp;gt;rendererfactory = &#039;theme_overridden_renderer_factory&#039;;                                                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a list of blocks that are required to exist on all pages for this theme to function correctly. For example               &lt;br /&gt;
// bootstrap base requires the settings and navigation blocks because otherwise there would be no way to navigate to all the        &lt;br /&gt;
// pages in Moodle. Boost does not require these blocks because it provides other ways to navigate built into the theme.            &lt;br /&gt;
$THEME-&amp;gt;requiredblocks = &#039;&#039;;   &lt;br /&gt;
&lt;br /&gt;
// This is a feature that tells the blocks library not to use the &amp;quot;Add a block&amp;quot; block. We don&#039;t want this in boost based themes because&lt;br /&gt;
// it forces a block region into the page when editing is enabled and it takes up too much room.&lt;br /&gt;
$THEME-&amp;gt;addblockposition = BLOCK_ADDBLOCK_POSITION_FLATNAV;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ready set go! ===&lt;br /&gt;
If you have been following along - now we are at the point where we can actually install and test our new theme. Try it now by visiting the admin notifications page to install the new plugin, and then choosing the new theme from the theme selector.&lt;br /&gt;
&lt;br /&gt;
[[https://docs.moodle.org/en/Standard_themes#Theme_selector Theme selector]]&lt;br /&gt;
&lt;br /&gt;
When you choose the new theme - you will find that it looks exactly the same as Boost. At this point with our minimal configuration - we are inheriting almost everything from our parent theme including styles and templates. You will notice though that we don&#039;t inherit the settings from our parent theme. If you choose a different preset in Boost - it is not applied in this child theme.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&lt;br /&gt;
Note: make sure your config.php file contains $THEME-&amp;gt;hidefromselector = false; (or at least set to false) or else, your theme wont show up in theme selector.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What if I want the settings too? ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&lt;br /&gt;
This section is included for completeness - but it is not recommended for themes to utilise settings from their parents. To find out how to duplicate the settings from the parent theme so they operate independently skip to [[#Duplicate the settings from Boost]].&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If I want the settings from Boost to apply to my child theme as well I need to know a bit about how each of the settings in Boost is applied to make them work in my child theme.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Setting 1 - preset.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;preset&amp;quot; file is the file that is used as the main file for scss compilation. In Boost this is controlled by the theme config value:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {&lt;br /&gt;
    return theme_boost_get_main_scss_content($theme);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_boost&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this function is doing is checking for a theme setting &amp;quot;preset&amp;quot; and either fetching the file from Moodles internal file storage, or from the /preset/ folder. The function then returns the contents of this file.&lt;br /&gt;
&lt;br /&gt;
It does not automatically work for our child theme because we have no setting named &amp;quot;preset&amp;quot; in our child theme and this code is not searching the theme parents for the setting. If we wanted it to apply we could do this in our child theme:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This setting defines the main scss file for our theme to be compiled. We could set it to a static file in the scss folder or to a function which returns the SCSS based on theme settings.&lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {&lt;br /&gt;
&lt;br /&gt;
    // We need to load the config for our parent theme because that is where the preset setting is defined.&lt;br /&gt;
    $parentconfig = theme_config::load(&#039;boost&#039;);&lt;br /&gt;
    // Call a function from our parent themes lib.php file to fetch the content of the themes main SCSS file based on it&#039;s own config, not ours.&lt;br /&gt;
    return theme_boost_get_main_scss_content($parentconfig);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings 2+3 brandcolor + scsspre&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The way these settings work is they generate a chunk of SCSS to be prepended to the main scss file. In boost they work like this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;prescsscallback = &#039;theme_boost_get_pre_scss&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_pre_scss($theme) {                                                                                         &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $configurable = [                                                                                                               &lt;br /&gt;
        // Config key =&amp;gt; [variableName, ...].                                                                                       &lt;br /&gt;
        &#039;brandcolor&#039; =&amp;gt; [&#039;brand-primary&#039;],                                                                                          &lt;br /&gt;
    ];                                                                                                                              &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Prepend variables first.                                                                                                     &lt;br /&gt;
    foreach ($configurable as $configkey =&amp;gt; $targets) {                                                                             &lt;br /&gt;
        $value = isset($theme-&amp;gt;settings-&amp;gt;{$configkey}) ? $theme-&amp;gt;settings-&amp;gt;{$configkey} : null;                                     &lt;br /&gt;
        if (empty($value)) {                                                                                                        &lt;br /&gt;
            continue;                                                                                                               &lt;br /&gt;
        }                                                                                                                           &lt;br /&gt;
        array_map(function($target) use (&amp;amp;$scss, $value) {                                                                          &lt;br /&gt;
            $scss .= &#039;$&#039; . $target . &#039;: &#039; . $value . &amp;quot;;\n&amp;quot;;                                                                         &lt;br /&gt;
        }, (array) $targets);                                                                                                       &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Prepend pre-scss.                                                                                                            &lt;br /&gt;
    if (!empty($theme-&amp;gt;settings-&amp;gt;scsspre)) {                                                                                        &lt;br /&gt;
        $scss .= $theme-&amp;gt;settings-&amp;gt;scsspre;                                                                                         &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}  &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this code is doing is: &lt;br /&gt;
* looping over a list of theme settings that map to a SCSS variable and building some SCSS to initialise that variable from the setting. In Boost there is only one * brandprimary - but if we wanted to expose more bootstrap variables as theme settings we could use this function as a template in our child theme and add more settings to the $configurable array.&lt;br /&gt;
* Adding all of the raw SCSS from the scsspre theme setting&lt;br /&gt;
* Returning the whole thing as a string to be added before the main scss file.&lt;br /&gt;
&lt;br /&gt;
If we want this code to work in our child theme, using the settings from Boost we could do this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is a function that returns some SCSS as a string to prepend to the main SCSS file.                                          &lt;br /&gt;
$THEME-&amp;gt;prescsscallback = &#039;theme_photo_get_pre_scss&#039;;               &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Function to return the SCSS to prepend to our main SCSS for this theme.&lt;br /&gt;
// Note the function name starts with the component name because this is a global function and we don&#039;t want namespace clashes.&lt;br /&gt;
function theme_photo_get_pre_scss($theme) {&lt;br /&gt;
    // Load the settings from the parent.                                                                                           &lt;br /&gt;
    $theme = theme_config::load(&#039;boost&#039;);                                                                                           &lt;br /&gt;
    // Call the parent themes get_pre_scss function.                                                                                &lt;br /&gt;
    return theme_boost_get_pre_scss($theme);                         &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Setting 4 scss (post)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The final setting from Boost is a raw text field which adds SCSS to the end of the main SCSS file. This is a useful place to add style rules as they will override previously defined styles with the same specificity. It is applied in Boost by the following lines:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;extrascsscallback = &#039;theme_boost_get_extra_scss&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_extra_scss($theme) {                                                                                       &lt;br /&gt;
    return !empty($theme-&amp;gt;settings-&amp;gt;scss) ? $theme-&amp;gt;settings-&amp;gt;scss : &#039;&#039;;                                                            &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is just returning the value of the setting as a string.&lt;br /&gt;
&lt;br /&gt;
To make this setting apply in our child theme too - we use similar code to the previous sections.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is a function that returns some SCSS as a string to append to the main SCSS file.                                          &lt;br /&gt;
$THEME-&amp;gt;extrascsscallback = &#039;theme_photo_get_extra_scss&#039;;               &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Function to return the SCSS to append to our main SCSS for this theme.&lt;br /&gt;
// Note the function name starts with the component name because this is a global function and we don&#039;t want namespace clashes.&lt;br /&gt;
function theme_photo_get_extra_scss($theme) {&lt;br /&gt;
    // Load the settings from the parent.                                                                                           &lt;br /&gt;
    $theme = theme_config::load(&#039;boost&#039;);                                                                                           &lt;br /&gt;
    // Call the parent themes get_extra_scss function.                                                                                &lt;br /&gt;
    return theme_boost_get_extra_scss($theme);                         &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Duplicate the settings from Boost  ===&lt;br /&gt;
&lt;br /&gt;
This is the recommended way to extend boost as your child theme will not be affected by changes to the Boost settings, and both themes can be in use with different settings applied.&lt;br /&gt;
&lt;br /&gt;
All that needs to happen is to create theme settings in the child theme that match each of the settings in the parent theme. You will need to add matching language strings for each of these settings in the language file.&lt;br /&gt;
&lt;br /&gt;
This example shows how to do it - We are re-using the nice looking theme_boost_admin_settingspage_tabs class from boost and creating duplicate versions of each of the settings.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is used for performance, we don&#039;t need to know about these settings on every page in Moodle, only when                      &lt;br /&gt;
// we are looking at the admin settings pages.                                                                                      &lt;br /&gt;
if ($ADMIN-&amp;gt;fulltree) {                                                                                                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Boost provides a nice setting page which splits settings onto separate tabs. We want to use it here.                         &lt;br /&gt;
    $settings = new theme_boost_admin_settingspage_tabs(&#039;themesettingphoto&#039;, get_string(&#039;configtitle&#039;, &#039;theme_photo&#039;));             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Each page is a tab - the first is the &amp;quot;General&amp;quot; tab.                                                                         &lt;br /&gt;
    $page = new admin_settingpage(&#039;theme_photo_general&#039;, get_string(&#039;generalsettings&#039;, &#039;theme_photo&#039;));                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Replicate the preset setting from boost.                                                                                     &lt;br /&gt;
    $name = &#039;theme_photo/preset&#039;;                                                                                                   &lt;br /&gt;
    $title = get_string(&#039;preset&#039;, &#039;theme_photo&#039;);                                                                                   &lt;br /&gt;
    $description = get_string(&#039;preset_desc&#039;, &#039;theme_photo&#039;);                                                                        &lt;br /&gt;
    $default = &#039;default.scss&#039;;                                                                                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // We list files in our own file area to add to the drop down. We will provide our own function to                              &lt;br /&gt;
    // load all the presets from the correct paths.                                                                                 &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
    $files = $fs-&amp;gt;get_area_files($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;itemid, filepath, filename&#039;, false);                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $choices = [];                                                                                                                  &lt;br /&gt;
    foreach ($files as $file) {                                                                                                     &lt;br /&gt;
        $choices[$file-&amp;gt;get_filename()] = $file-&amp;gt;get_filename();                                                                    &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
    // These are the built in presets from Boost.                                                                                   &lt;br /&gt;
    $choices[&#039;default.scss&#039;] = &#039;default.scss&#039;;                                                                                      &lt;br /&gt;
    $choices[&#039;plain.scss&#039;] = &#039;plain.scss&#039;;                                                                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $setting = new admin_setting_configselect($name, $title, $description, $default, $choices);                                     &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Preset files setting.                                                                                                        &lt;br /&gt;
    $name = &#039;theme_photo/presetfiles&#039;;                                                                                              &lt;br /&gt;
    $title = get_string(&#039;presetfiles&#039;,&#039;theme_photo&#039;);                                                                               &lt;br /&gt;
    $description = get_string(&#039;presetfiles_desc&#039;, &#039;theme_photo&#039;);                                                                   &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;preset&#039;, 0,                                         &lt;br /&gt;
        array(&#039;maxfiles&#039; =&amp;gt; 20, &#039;accepted_types&#039; =&amp;gt; array(&#039;.scss&#039;)));                                                               &lt;br /&gt;
    $page-&amp;gt;add($setting);     &lt;br /&gt;
&lt;br /&gt;
    // Variable $brand-color.                                                                                                       &lt;br /&gt;
    // We use an empty default value because the default colour should come from the preset.                                        &lt;br /&gt;
    $name = &#039;theme_photo/brandcolor&#039;;                                                                                               &lt;br /&gt;
    $title = get_string(&#039;brandcolor&#039;, &#039;theme_photo&#039;);                                                                               &lt;br /&gt;
    $description = get_string(&#039;brandcolor_desc&#039;, &#039;theme_photo&#039;);                                                                    &lt;br /&gt;
    $setting = new admin_setting_configcolourpicker($name, $title, $description, &#039;&#039;);                                               &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Must add the page after definiting all the settings!                                                                         &lt;br /&gt;
    $settings-&amp;gt;add($page);                                                                                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Advanced settings.                                                                                                           &lt;br /&gt;
    $page = new admin_settingpage(&#039;theme_photo_advanced&#039;, get_string(&#039;advancedsettings&#039;, &#039;theme_photo&#039;));                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Raw SCSS to include before the content.                                                                                      &lt;br /&gt;
    $setting = new admin_setting_configtextarea(&#039;theme_photo/scsspre&#039;,                                                              &lt;br /&gt;
        get_string(&#039;rawscsspre&#039;, &#039;theme_photo&#039;), get_string(&#039;rawscsspre_desc&#039;, &#039;theme_photo&#039;), &#039;&#039;, PARAM_RAW);                      &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Raw SCSS to include after the content.                                                                                       &lt;br /&gt;
    $setting = new admin_setting_configtextarea(&#039;theme_photo/scss&#039;, get_string(&#039;rawscss&#039;, &#039;theme_photo&#039;),                           &lt;br /&gt;
        get_string(&#039;rawscss_desc&#039;, &#039;theme_photo&#039;), &#039;&#039;, PARAM_RAW);                                                                  &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $settings-&amp;gt;add($page);                                                                                                          &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lang/en/theme_photo.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
// The name of the second tab in the theme settings.                                                                                &lt;br /&gt;
$string[&#039;advancedsettings&#039;] = &#039;Advanced settings&#039;;                                                                                  &lt;br /&gt;
// The brand colour setting.                                                                                                        &lt;br /&gt;
$string[&#039;brandcolor&#039;] = &#039;Brand colour&#039;;                                                                                             &lt;br /&gt;
// The brand colour setting description.                                                                                            &lt;br /&gt;
$string[&#039;brandcolor_desc&#039;] = &#039;The accent colour.&#039;;     &lt;br /&gt;
// A description shown in the admin theme selector.                                                                                 &lt;br /&gt;
$string[&#039;choosereadme&#039;] = &#039;Theme photo is a child theme of Boost. It adds the ability to upload background photos.&#039;;                &lt;br /&gt;
// Name of the settings pages.                                                                                                      &lt;br /&gt;
$string[&#039;configtitle&#039;] = &#039;Photo settings&#039;;                                                                                          &lt;br /&gt;
// Name of the first settings tab.                                                                                                  &lt;br /&gt;
$string[&#039;generalsettings&#039;] = &#039;General settings&#039;;                                                                                    &lt;br /&gt;
// The name of our plugin.                                                                                                          &lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Photo&#039;;                                                                                                    &lt;br /&gt;
// Preset files setting.                                                                                                            &lt;br /&gt;
$string[&#039;presetfiles&#039;] = &#039;Additional theme preset files&#039;;                                                                           &lt;br /&gt;
// Preset files help text.                                                                                                          &lt;br /&gt;
$string[&#039;presetfiles_desc&#039;] = &#039;Preset files can be used to dramatically alter the appearance of the theme. See &amp;lt;a href=https://docs.moodle.org/dev/Boost_Presets&amp;gt;Boost presets&amp;lt;/a&amp;gt; for information on creating and sharing your own preset files, and see the &amp;lt;a href=http://moodle.net/boost&amp;gt;Presets repository&amp;lt;/a&amp;gt; for presets that others have shared.&#039;;&lt;br /&gt;
// Preset setting.                                                                                                                  &lt;br /&gt;
$string[&#039;preset&#039;] = &#039;Theme preset&#039;;                                                                                                 &lt;br /&gt;
// Preset help text.                                                                                                                &lt;br /&gt;
$string[&#039;preset_desc&#039;] = &#039;Pick a preset to broadly change the look of the theme.&#039;;                                                  &lt;br /&gt;
// Raw SCSS setting.                                                                                                                &lt;br /&gt;
$string[&#039;rawscss&#039;] = &#039;Raw SCSS&#039;;                                                                                                    &lt;br /&gt;
// Raw SCSS setting help text.                                                                                                      &lt;br /&gt;
$string[&#039;rawscss_desc&#039;] = &#039;Use this field to provide SCSS or CSS code which will be injected at the end of the style sheet.&#039;;       &lt;br /&gt;
// Raw initial SCSS setting.                                                                                                        &lt;br /&gt;
$string[&#039;rawscsspre&#039;] = &#039;Raw initial SCSS&#039;;                                                                                         &lt;br /&gt;
// Raw initial SCSS setting help text.                                                                                              &lt;br /&gt;
$string[&#039;rawscsspre_desc&#039;] = &#039;In this field you can provide initialising SCSS code, it will be injected before everything else. Most of the time you will use this setting to define variables.&#039;;&lt;br /&gt;
// We need to include a lang string for each block region.                                                                          &lt;br /&gt;
$string[&#039;region-side-pre&#039;] = &#039;Right&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We aren&#039;t quite there yet as you will notice if you try and upload a preset file and then choose it. The &amp;quot;theme_boost_get_main_scss_content&amp;quot; function from Boost is expecting the preset files to be stored in a file area for theme_boost only. We need to add this function to our own theme and tweak it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is the function that returns the SCSS source for the main file in our theme. We override the boost version because          &lt;br /&gt;
// we want to allow presets uploaded to our own theme file area to be selected in the preset list.                                  &lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {                                                                                                   &lt;br /&gt;
    return theme_photo_get_main_scss_content($theme);                                                                               &lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        // This preset file was fetched from the file area for theme_photo and not theme_boost (see the line above).                &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}             &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Stop and try it out ===&lt;br /&gt;
So now what is working and what isn&#039;t. Well - everything should be working and you should have a nice new theme extending boost with it&#039;s own settings pages. When Boost gets updates for bug fixes your new theme will inherit those fixes as it inherits all the SCSS and templates from theme boost. In addition your new theme will accept preset files and supports all the same features and settings as boost, ready to add more.&lt;br /&gt;
&lt;br /&gt;
== Take it further ==&lt;br /&gt;
Now we have our very nice starting point we can start changing or adding features, customising templates and output or tweaking the SCSS.&lt;br /&gt;
&lt;br /&gt;
=== Add some new settings ===&lt;br /&gt;
&lt;br /&gt;
From this point in the tutorial we will start adding features to our theme to extend it and make it AWESOME!&lt;br /&gt;
&lt;br /&gt;
Lets start with a new setting to set a background image on the login page. As you saw earlier, our theme defines it&#039;s list of settings in a file called settings.php. See [[Admin settings]] for more information about adding admin settings to any plugin. All of the different kinds of admin settings can be found in lib/adminlib.php. In our case we will want to add a setting which allows an admin to upload an image file. This is an &amp;quot;admin_setting_configstoredfile&amp;quot; and we add it to our theme by adding  this code to the settings.php file (inside the &amp;quot;if ($ADMIN-&amp;gt;fulltree) {&amp;quot; condition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    // Login page background setting.                                                                                               &lt;br /&gt;
    // We use variables for readability.                                                                                            &lt;br /&gt;
    $name = &#039;theme_photo/loginbackgroundimage&#039;;                                                                                     &lt;br /&gt;
    $title = get_string(&#039;loginbackgroundimage&#039;, &#039;theme_photo&#039;);                                                                     &lt;br /&gt;
    $description = get_string(&#039;loginbackgroundimage_desc&#039;, &#039;theme_photo&#039;);                                                          &lt;br /&gt;
    // This creates the new setting.                                                                                                &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;loginbackgroundimage&#039;);                             &lt;br /&gt;
    // This means that theme caches will automatically be cleared when this setting is changed.                                     &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    // We always have to add the setting to a page for it to have any effect.                                                       &lt;br /&gt;
    $page-&amp;gt;add($setting);       &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need to add new lang strings to our language file.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lang/en/theme_photo.php&amp;quot;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Background image for login page.                                                                                                 &lt;br /&gt;
$string[&#039;loginbackgroundimage&#039;] = &#039;Login page background image&#039;;                                                                    &lt;br /&gt;
// Background image for login page.                                                                                                 &lt;br /&gt;
$string[&#039;loginbackgroundimage_desc&#039;] = &#039;An image that will be stretched to fill the background of the login page.&#039;;                 &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have a new setting that lets us upload a file - but it doesn&#039;t actually do anything yet. We need to update the theme to set this image background on the login page.&lt;br /&gt;
&lt;br /&gt;
In order to change the SCSS for our theme we will add 2 additional SCSS files and include them before and after our main scss.&lt;br /&gt;
&lt;br /&gt;
We already have a function in our lib.php file which fetches the main SCSS for our theme. This is a good point to include additional SCSS files. We can add 2 lines to the end of this function to achieve this.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        // This preset file was fetched from the file area for theme_photo and not theme_boost (see the line above).                &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Pre CSS - this is loaded AFTER any prescss from the setting but before the main scss.                                        &lt;br /&gt;
    $pre = file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/photo/scss/pre.scss&#039;);                                                         &lt;br /&gt;
    // Post CSS - this is loaded AFTER the main scss but before the extra scss from the setting.                                    &lt;br /&gt;
    $post = file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/photo/scss/post.scss&#039;);                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Combine them together.                                                                                                       &lt;br /&gt;
    return $pre . &amp;quot;\n&amp;quot; . $scss . &amp;quot;\n&amp;quot; . $post;                                                                                      &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;scss/pre.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
// Pre SCSS for the theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;scss/post.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
// Post SCSS for the theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Why do we use pre and post SCSS? ====&lt;br /&gt;
SCSS/SASS is a powerful language for creating CSS. It supports variables, functions, loops just like php. For lots of information and an introduction to SCSS read about [https://en.wikipedia.org/wiki/Sass_(stylesheet_language) Sass on wikipedia]. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pre SCSS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In Boost we use many variables when creating style rules.&lt;br /&gt;
&lt;br /&gt;
When declaring a variable in SCSS - it is best practice to define it like this:&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
$mycoolcolour: #FF0 !default;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this means is - if this variable is not defined already - set it to the hex value &#039;#FF0&#039;;&lt;br /&gt;
&lt;br /&gt;
So by setting this variable in some PRE scss we can override the default value of this variable everywhere it is used. Boost is built with the [https://v4-alpha.getbootstrap.com/ Bootstrap 4 (Alpha 4)] CSS Framework. This is a framework which uses SCSS to provide many extremely useful layouts and components which can be reused without adding specific CSS rules to style every page. Because bootstrap consistently uses variables we can customise many of these components easily by setting the value of the variables before we include the Bootstrap SCSS files.&lt;br /&gt;
&lt;br /&gt;
Many variables are available in /theme/boost/scss/bootstrap/_variables.scss - as an example we can change the look of all buttons and input fields with this one variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
$border-radius: 8px;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Post SCSS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Post SCSS is useful for defining full CSS rules. Because they are included last, they override any previous matching selector with the same [https://en.wikipedia.org/wiki/Cascading_Style_Sheets#Specificity Specificity].&lt;br /&gt;
&lt;br /&gt;
=== Tips for customising Moodle with SCSS (or CSS) ===&lt;br /&gt;
Some handy things to know when you are new to theming is that Moodle adds some classes to every page that helps you target a specific page or set of pages with some style rules. &lt;br /&gt;
&lt;br /&gt;
If you inspect a moodle page and look at the body tag you will see a long list of classes e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code html&amp;gt;&lt;br /&gt;
&amp;lt;body id=&amp;quot;page-course-view-weeks&amp;quot; class=&amp;quot;format-weeks  path-course path-course-view safari dir-ltr lang-en yui-skin-sam yui3-skin-sam damyon-per-in-moodle-com--stable_master pagelayout-course course-11 context-497 category-1 drawer-open-left jsenabled&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can see from this example that each page gets an id. This is a simplified representation of the current page in the navigation. In this example we are looking at the course page and this course is using the weeks format. &lt;br /&gt;
&lt;br /&gt;
The classes on the body tag can also be used to target a page or set of pages.&lt;br /&gt;
* &amp;lt;code&amp;gt;format-weeks&amp;lt;/code&amp;gt; The course format&lt;br /&gt;
* &amp;lt;code&amp;gt;path-course path-course-view&amp;lt;/code&amp;gt; The parts of the bread-crumb leading up to the current page (The current page is what goes in the id)&lt;br /&gt;
* &amp;lt;code&amp;gt;safari&amp;lt;/code&amp;gt; Some server side guessing of the browser type - it&#039;s not accurate so I would not rely on it&lt;br /&gt;
* &amp;lt;code&amp;gt;dir-ltr&amp;lt;/code&amp;gt; The direction of the current language for the page ( dir-rtl for RTL languages )&lt;br /&gt;
* &amp;lt;code&amp;gt;lang-en&amp;lt;/code&amp;gt; The current language of the page&lt;br /&gt;
* &amp;lt;code&amp;gt;yui*&amp;lt;/code&amp;gt; Legacy yui classes - ignore these&lt;br /&gt;
* &amp;lt;code&amp;gt;damyon-per-in-moodle-com--stable_master&amp;lt;/code&amp;gt; The current hostname for the site + the site name&lt;br /&gt;
* &amp;lt;code&amp;gt;pagelayout-course&amp;lt;/code&amp;gt; The layout type for the current page&lt;br /&gt;
* &amp;lt;code&amp;gt;course-11&amp;lt;/code&amp;gt; The id of the current course&lt;br /&gt;
* &amp;lt;code&amp;gt;context-497&amp;lt;/code&amp;gt; The current context id&lt;br /&gt;
* &amp;lt;code&amp;gt;category-1&amp;lt;/code&amp;gt; The category for the current course&lt;br /&gt;
* &amp;lt;code&amp;gt;drawer-open-left&amp;lt;/code&amp;gt; Added / removed when the navigation drawer is opened / closed in Boost&lt;br /&gt;
* &amp;lt;code&amp;gt;jsenabled&amp;lt;/code&amp;gt; True if the browser supports javascript&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/dev/Themes_overview#.3Cbody.3E_CSS_id_and_classes Read about Body id and classes].&lt;br /&gt;
&lt;br /&gt;
In our example the page layout is the most useful here as we have a specific page layout for login pages. We can now craft a rule that applies a background image only to login pages using &amp;quot;body.pagelayout-login&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How do we refer to an image in SCSS ? ===&lt;br /&gt;
So now we can add a rule to the post.scss which will set the background image for the login page. First we need to know how to construct a url to the background images from our stylesheet. &lt;br /&gt;
&lt;br /&gt;
In stylesheets in Moodle we can use a special pix tag to refer to images from our theme. The rule to attach the background image looks like this:&lt;br /&gt;
&#039;&#039;scss/post.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
body.pagelayout-login {                                                                                                             &lt;br /&gt;
    background-image: url([[pix:theme_photo|loginbackgroundimage]]);                                                                &lt;br /&gt;
    background-size: cover;                                                                                                         &lt;br /&gt;
}                          &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are 2 important parts to this tag (the bit in square brackets). The first is &amp;quot;theme_photo&amp;quot;. In this case we are passing a component name, the image serving code in theme_config::resolve_image_location() will then look for an image file in several locations. One of these is in &amp;quot;$CFG-&amp;gt;dataroot/pix_plugins/$type/$plugin/$image&amp;quot;. We can use this to make sure the image gets served correctly by copying the file saved in the setting to this location every time it is updated. (There is an alterative way we could do this by implementing pluginfile.php in our theme - which you can read about in the [[File API]] ).&lt;br /&gt;
&lt;br /&gt;
If we had just passed the value &amp;quot;theme&amp;quot; the image serving code would have looked for the image in the &amp;quot;pix&amp;quot; folder of our theme.&lt;br /&gt;
&lt;br /&gt;
So - we need this final change to copy the image file into our dataroot each time the setting is changed.&lt;br /&gt;
&lt;br /&gt;
In the settings file we will update the callback to a new function which we will define in our lib.php.&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Login page background setting.                                                                                               &lt;br /&gt;
    // We use variables for readability.                                                                                            &lt;br /&gt;
    $name = &#039;theme_photo/loginbackgroundimage&#039;;                                                                                     &lt;br /&gt;
    $title = get_string(&#039;loginbackgroundimage&#039;, &#039;theme_photo&#039;);                                                                     &lt;br /&gt;
    $description = get_string(&#039;loginbackgroundimage_desc&#039;, &#039;theme_photo&#039;);                                                          &lt;br /&gt;
    // This creates the new setting.                                                                                                &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;loginbackgroundimage&#039;);                             &lt;br /&gt;
    // This function will copy the image into the data_root location it can be served from.                                         &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_photo_update_settings_images&#039;);                                                            &lt;br /&gt;
    // We always have to add the setting to a page for it to have any effect.                                                       &lt;br /&gt;
    $page-&amp;gt;add($setting);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_update_settings_images($settingname) {                                                                         &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // The setting name that was updated comes as a string like &#039;s_theme_photo_loginbackgroundimage&#039;.                               &lt;br /&gt;
    // We split it on &#039;_&#039; characters.                                                                                               &lt;br /&gt;
    $parts = explode(&#039;_&#039;, $settingname);                                                                                            &lt;br /&gt;
    // And get the last one to get the setting name..                                                                               &lt;br /&gt;
    $settingname = end($parts);                                                                                                     &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Admin settings are stored in system context.                                                                                 &lt;br /&gt;
    $syscontext = context_system::instance();                                                                                       &lt;br /&gt;
    // This is the component name the setting is stored in.                                                                         &lt;br /&gt;
    $component = &#039;theme_photo&#039;;                                                                                                     &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // This is the value of the admin setting which is the filename of the uploaded file.                                           &lt;br /&gt;
    $filename = get_config($component, $settingname);                                                                               &lt;br /&gt;
    // We extract the file extension because we want to preserve it.                                                                &lt;br /&gt;
    $extension = substr($filename, strrpos($filename, &#039;.&#039;) + 1);                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // This is the path in the moodle internal file system.                                                                         &lt;br /&gt;
    $fullpath = &amp;quot;/{$syscontext-&amp;gt;id}/{$component}/{$settingname}/0{$filename}&amp;quot;;                                                      &lt;br /&gt;
    // Get an instance of the moodle file storage.                                                                                  &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
    // This is an efficient way to get a file if we know the exact path.                                                            &lt;br /&gt;
    if ($file = $fs-&amp;gt;get_file_by_hash(sha1($fullpath))) {                                                                           &lt;br /&gt;
        // We got the stored file - copy it to dataroot.                                                                            &lt;br /&gt;
        // This location matches the searched for location in theme_config::resolve_image_location.                                 &lt;br /&gt;
        $pathname = $CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039; . $settingname . &#039;.&#039; . $extension;                                 &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // This pattern matches any previous files with maybe different file extensions.                                            &lt;br /&gt;
        $pathpattern = $CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039; . $settingname . &#039;.*&#039;;                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Make sure this dir exists.                                                                                               &lt;br /&gt;
        @mkdir($CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039;, $CFG-&amp;gt;directorypermissions, true);                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Delete any existing files for this setting.                                                                              &lt;br /&gt;
        foreach (glob($pathpattern) as $filename) {                                                                                 &lt;br /&gt;
            @unlink($filename);                                                                                                     &lt;br /&gt;
        }                                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Copy the current file to this location.                                                                                  &lt;br /&gt;
        $file-&amp;gt;copy_content_to($pathname);                                                                                          &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Reset theme caches.                                                                                                          &lt;br /&gt;
    theme_reset_all_caches();                                                                                                       &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I won&#039;t show it here - but it is now easy to add a new background image setting for every layout type. I can re-use this theme_photo_update_settings_images callback for each one - so all I have to do is add the setting to the settings.php file, add the SCSS rule to the scss/post.scss file and add the lang strings to the language file.&lt;br /&gt;
&lt;br /&gt;
Thats it for this tutorial, but there are [[:Category:Themes| more Themes docs]] to browse.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Themes]]&lt;/div&gt;</summary>
		<author><name>Meeth</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Creating_a_theme_based_on_boost&amp;diff=57739</id>
		<title>Creating a theme based on boost</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Creating_a_theme_based_on_boost&amp;diff=57739"/>
		<updated>2020-07-31T10:30:59Z</updated>

		<summary type="html">&lt;p&gt;Meeth: Undo revision 57735 by Meeth (talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 3.2}}&lt;br /&gt;
{{Template:Themes}}&lt;br /&gt;
&lt;br /&gt;
This is a tutorial for how to create a new theme in any version of Moodle from 3.2 and later.&lt;br /&gt;
&lt;br /&gt;
Moodle 3.2 introduced a new core theme named &amp;quot;Boost&amp;quot; which is a great starting point for themers wanting to build a modern Moodle theme utilising all the latest features available to themes in Moodle.  If you aren&#039;t sure where to start, then START HERE!  :-)&lt;br /&gt;
&lt;br /&gt;
== Getting started ==&lt;br /&gt;
What is a theme? A theme in Moodle is just another type of plugin that can be developed. Themes are responsible for setting up the structure of each page and have the ability to customise the output of any page in Moodle.&lt;br /&gt;
&lt;br /&gt;
This tutorial is based on a working theme named &amp;quot;theme_photo&amp;quot; you can download it or view the source code for it here: https://github.com/damyon/moodle-theme_photo&lt;br /&gt;
&lt;br /&gt;
=== Choosing a name ===&lt;br /&gt;
Your new theme will need a name. Try and think of something short and memorable - and make sure it is not a name that has already been used by someone else. A quick search on the moodle.org/plugins can save you a lot of work renaming things later.&lt;br /&gt;
&lt;br /&gt;
Lets call our new example theme &amp;quot;photo&amp;quot; as we will add some settings to allow &amp;quot;photos&amp;quot; in various places in Moodle.&lt;br /&gt;
&lt;br /&gt;
=== Starting files ===&lt;br /&gt;
As a plugin, themes must start with the basic structure of a plugin in Moodle. See https://docs.moodle.org/dev/Tutorial#The_skeleton_of_your_plugin for an overview of the files common to all plugins in Moodle.&lt;br /&gt;
&lt;br /&gt;
Following this guide we can start creating our theme. First we create the folder for the new theme under &amp;quot;/theme/&amp;quot; folder in the Moodle root directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
/theme/photo/&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we need to add some standard plugin files to our theme. First is version.php&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/theme/photo/version.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the version of the plugin.                                                                                               &lt;br /&gt;
$plugin-&amp;gt;version = &#039;2016102100&#039;;                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the version of Moodle this plugin requires.                                                                              &lt;br /&gt;
$plugin-&amp;gt;requires = &#039;2016070700&#039;;                                                                                                   &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the component name of the plugin - it always starts with &#039;theme_&#039;                                                        &lt;br /&gt;
// for themes and should be the same as the name of the folder.                                                                     &lt;br /&gt;
$plugin-&amp;gt;component = &#039;theme_photo&#039;;                                                                                                 &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a list of plugins, this plugin depends on (and their versions).                                                          &lt;br /&gt;
$plugin-&amp;gt;dependencies = [                                                                                                           &lt;br /&gt;
    &#039;theme_boost&#039; =&amp;gt; &#039;2016102100&#039;                                                                                                   &lt;br /&gt;
];                                                                              &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need a language file so that all our strings can be translated into different languages. The name of this file is the component name of our plugin and it sits in the lang/en/ folder for our plugin. We can include translations of our plugin, but we can also provide translations via the https://lang.moodle.org/ website once our plugin has been published to the plugins database at http://www.moodle.org/plugins/.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/theme/photo/lang/en/theme_photo.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// A description shown in the admin theme selector.                                                                                 &lt;br /&gt;
$string[&#039;choosereadme&#039;] = &#039;Theme photo is a child theme of Boost. It adds the ability to upload background photos.&#039;;                &lt;br /&gt;
// The name of our plugin.                                                                                                          &lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Photo&#039;;                                                                                                    &lt;br /&gt;
// We need to include a lang string for each block region.                                                                          &lt;br /&gt;
$string[&#039;region-side-pre&#039;] = &#039;Right&#039;;                                         &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Theme specific files ===&lt;br /&gt;
Theme plugins have a few more standard files they need to define. &lt;br /&gt;
&lt;br /&gt;
Themes require a favicon file to show in the address bar. See [[http://docs.moodle.org/en/Favicon Favicon]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;pix/favicon.ico&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(Image file not shown).&lt;br /&gt;
&lt;br /&gt;
Themes also require an example screenshot to be displayed in the theme selector.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;pix/screenshot.jpg&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(Image file not shown).&lt;br /&gt;
&lt;br /&gt;
Themes require a lib.php file. This file contains callbacks used by various API&#039;s in Moodle. Initially this file can be empty, but as we add features to our theme we will need to add some functions here.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
// We will add callbacks here as we add features to our theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Theme config goes in a config.php file. This is one of the most important files in our theme. Once we add this file we will be ready to test our theme for the first time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
// $THEME is defined before this page is included and we can define settings by adding properties to this global object.            &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// The first setting we need is the name of the theme. This should be the last part of the component name, and the same             &lt;br /&gt;
// as the directory name for our theme.                                                                                             &lt;br /&gt;
$THEME-&amp;gt;name = &#039;photo&#039;;                                                                                                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This setting list the style sheets we want to include in our theme. Because we want to use SCSS instead of CSS - we won&#039;t        &lt;br /&gt;
// list any style sheets. If we did we would list the name of a file in the /style/ folder for our theme without any css file      &lt;br /&gt;
// extensions.                                                                                                                      &lt;br /&gt;
$THEME-&amp;gt;sheets = [];                                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a setting that can be used to provide some styling to the content in the TinyMCE text editor. This is no longer the      &lt;br /&gt;
// default text editor and &amp;quot;Atto&amp;quot; does not need this setting so we won&#039;t provide anything. If we did it would work the same         &lt;br /&gt;
// as the previous setting - listing a file in the /styles/ folder.                                                                 &lt;br /&gt;
$THEME-&amp;gt;editor_sheets = [];                                                                                                         &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a critical setting. We want to inherit from theme_boost because it provides a great starting point for SCSS bootstrap4   &lt;br /&gt;
// themes. We could add more than one parent here to inherit from multiple parents, and if we did they would be processed in        &lt;br /&gt;
// order of importance (later themes overriding earlier ones). Things we will inherit from the parent theme include                 &lt;br /&gt;
// styles and mustache templates and some (not all) settings.                                                                       &lt;br /&gt;
$THEME-&amp;gt;parents = [&#039;boost&#039;];                                                                                                        &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// A dock is a way to take blocks out of the page and put them in a persistent floating area on the side of the page. Boost         &lt;br /&gt;
// does not support a dock so we won&#039;t either - but look at bootstrapbase for an example of a theme with a dock.                    &lt;br /&gt;
$THEME-&amp;gt;enable_dock = false;                                                                                                        &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is an old setting used to load specific CSS for some YUI JS. We don&#039;t need it in Boost based themes because Boost           &lt;br /&gt;
// provides default styling for the YUI modules that we use. It is not recommended to use this setting anymore.                     &lt;br /&gt;
$THEME-&amp;gt;yuicssmodules = array();                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// Most themes will use this rendererfactory as this is the one that allows the theme to override any other renderer.               &lt;br /&gt;
$THEME-&amp;gt;rendererfactory = &#039;theme_overridden_renderer_factory&#039;;                                                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a list of blocks that are required to exist on all pages for this theme to function correctly. For example               &lt;br /&gt;
// bootstrap base requires the settings and navigation blocks because otherwise there would be no way to navigate to all the        &lt;br /&gt;
// pages in Moodle. Boost does not require these blocks because it provides other ways to navigate built into the theme.            &lt;br /&gt;
$THEME-&amp;gt;requiredblocks = &#039;&#039;;   &lt;br /&gt;
&lt;br /&gt;
// This is a feature that tells the blocks library not to use the &amp;quot;Add a block&amp;quot; block. We don&#039;t want this in boost based themes because&lt;br /&gt;
// it forces a block region into the page when editing is enabled and it takes up too much room.&lt;br /&gt;
$THEME-&amp;gt;addblockposition = BLOCK_ADDBLOCK_POSITION_FLATNAV;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ready set go! ===&lt;br /&gt;
If you have been following along - now we are at the point where we can actually install and test our new theme. Try it now by visiting the admin notifications page to install the new plugin, and then choosing the new theme from the theme selector.&lt;br /&gt;
&lt;br /&gt;
[[https://docs.moodle.org/en/Standard_themes#Theme_selector Theme selector]]&lt;br /&gt;
&lt;br /&gt;
When you choose the new theme - you will find that it looks exactly the same as Boost. At this point with our minimal configuration - we are inheriting almost everything from our parent theme including styles and templates. You will notice though that we don&#039;t inherit the settings from our parent theme. If you choose a different preset in Boost - it is not applied in this child theme.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&lt;br /&gt;
Note: make sure your config.php file contains $THEME-&amp;gt;hidefromselector = false; (or at least set to false) or else, your theme wont show up in theme selector.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What if I want the settings too? ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&lt;br /&gt;
This section is included for completeness - but it is not recommended for themes to utilise settings from their parents. To find out how to duplicate the settings from the parent theme so they operate independently skip to [[#Duplicate the settings from Boost]].&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If I want the settings from Boost to apply to my child theme as well I need to know a bit about how each of the settings in Boost is applied to make them work in my child theme.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Setting 1 - preset.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;preset&amp;quot; file is the file that is used as the main file for scss compilation. In Boost this is controlled by the theme config value:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {&lt;br /&gt;
    return theme_boost_get_main_scss_content($theme);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_boost&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this function is doing is checking for a theme setting &amp;quot;preset&amp;quot; and either fetching the file from Moodles internal file storage, or from the /preset/ folder. The function then returns the contents of this file.&lt;br /&gt;
&lt;br /&gt;
It does not automatically work for our child theme because we have no setting named &amp;quot;preset&amp;quot; in our child theme and this code is not searching the theme parents for the setting. If we wanted it to apply we could do this in our child theme:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This setting defines the main scss file for our theme to be compiled. We could set it to a static file in the scss folder or to a function which returns the SCSS based on theme settings.&lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {&lt;br /&gt;
&lt;br /&gt;
    // We need to load the config for our parent theme because that is where the preset setting is defined.&lt;br /&gt;
    $parentconfig = theme_config::load(&#039;boost&#039;);&lt;br /&gt;
    // Call a function from our parent themes lib.php file to fetch the content of the themes main SCSS file based on it&#039;s own config, not ours.&lt;br /&gt;
    return theme_boost_get_main_scss_content($parentconfig);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings 2+3 brandcolor + scsspre&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The way these settings work is they generate a chunk of SCSS to be prepended to the main scss file. In boost they work like this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;prescsscallback = &#039;theme_boost_get_pre_scss&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_pre_scss($theme) {                                                                                         &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $configurable = [                                                                                                               &lt;br /&gt;
        // Config key =&amp;gt; [variableName, ...].                                                                                       &lt;br /&gt;
        &#039;brandcolor&#039; =&amp;gt; [&#039;brand-primary&#039;],                                                                                          &lt;br /&gt;
    ];                                                                                                                              &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Prepend variables first.                                                                                                     &lt;br /&gt;
    foreach ($configurable as $configkey =&amp;gt; $targets) {                                                                             &lt;br /&gt;
        $value = isset($theme-&amp;gt;settings-&amp;gt;{$configkey}) ? $theme-&amp;gt;settings-&amp;gt;{$configkey} : null;                                     &lt;br /&gt;
        if (empty($value)) {                                                                                                        &lt;br /&gt;
            continue;                                                                                                               &lt;br /&gt;
        }                                                                                                                           &lt;br /&gt;
        array_map(function($target) use (&amp;amp;$scss, $value) {                                                                          &lt;br /&gt;
            $scss .= &#039;$&#039; . $target . &#039;: &#039; . $value . &amp;quot;;\n&amp;quot;;                                                                         &lt;br /&gt;
        }, (array) $targets);                                                                                                       &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Prepend pre-scss.                                                                                                            &lt;br /&gt;
    if (!empty($theme-&amp;gt;settings-&amp;gt;scsspre)) {                                                                                        &lt;br /&gt;
        $scss .= $theme-&amp;gt;settings-&amp;gt;scsspre;                                                                                         &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}  &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this code is doing is: &lt;br /&gt;
* looping over a list of theme settings that map to a SCSS variable and building some SCSS to initialise that variable from the setting. In Boost there is only one * brandprimary - but if we wanted to expose more bootstrap variables as theme settings we could use this function as a template in our child theme and add more settings to the $configurable array.&lt;br /&gt;
* Adding all of the raw SCSS from the scsspre theme setting&lt;br /&gt;
* Returning the whole thing as a string to be added before the main scss file.&lt;br /&gt;
&lt;br /&gt;
If we want this code to work in our child theme, using the settings from Boost we could do this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is a function that returns some SCSS as a string to prepend to the main SCSS file.                                          &lt;br /&gt;
$THEME-&amp;gt;prescsscallback = &#039;theme_photo_get_pre_scss&#039;;               &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Function to return the SCSS to prepend to our main SCSS for this theme.&lt;br /&gt;
// Note the function name starts with the component name because this is a global function and we don&#039;t want namespace clashes.&lt;br /&gt;
function theme_photo_get_pre_scss($theme) {&lt;br /&gt;
    // Load the settings from the parent.                                                                                           &lt;br /&gt;
    $theme = theme_config::load(&#039;boost&#039;);                                                                                           &lt;br /&gt;
    // Call the parent themes get_pre_scss function.                                                                                &lt;br /&gt;
    return theme_boost_get_pre_scss($theme);                         &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Setting 4 scss (post)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The final setting from Boost is a raw text field which adds SCSS to the end of the main SCSS file. This is a useful place to add style rules as they will override previously defined styles with the same specificity. It is applied in Boost by the following lines:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;extrascsscallback = &#039;theme_boost_get_extra_scss&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_extra_scss($theme) {                                                                                       &lt;br /&gt;
    return !empty($theme-&amp;gt;settings-&amp;gt;scss) ? $theme-&amp;gt;settings-&amp;gt;scss : &#039;&#039;;                                                            &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is just returning the value of the setting as a string.&lt;br /&gt;
&lt;br /&gt;
To make this setting apply in our child theme too - we use similar code to the previous sections.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is a function that returns some SCSS as a string to append to the main SCSS file.                                          &lt;br /&gt;
$THEME-&amp;gt;extrascsscallback = &#039;theme_photo_get_extra_scss&#039;;               &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Function to return the SCSS to append to our main SCSS for this theme.&lt;br /&gt;
// Note the function name starts with the component name because this is a global function and we don&#039;t want namespace clashes.&lt;br /&gt;
function theme_photo_get_extra_scss($theme) {&lt;br /&gt;
    // Load the settings from the parent.                                                                                           &lt;br /&gt;
    $theme = theme_config::load(&#039;boost&#039;);                                                                                           &lt;br /&gt;
    // Call the parent themes get_extra_scss function.                                                                                &lt;br /&gt;
    return theme_boost_get_extra_scss($theme);                         &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Duplicate the settings from Boost  ===&lt;br /&gt;
&lt;br /&gt;
This is the recommended way to extend boost as your child theme will not be affected by changes to the Boost settings, and both themes can be in use with different settings applied.&lt;br /&gt;
&lt;br /&gt;
All that needs to happen is to create theme settings in the child theme that match each of the settings in the parent theme. You will need to add matching language strings for each of these settings in the language file.&lt;br /&gt;
&lt;br /&gt;
This example shows how to do it - We are re-using the nice looking theme_boost_admin_settingspage_tabs class from boost and creating duplicate versions of each of the settings.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is used for performance, we don&#039;t need to know about these settings on every page in Moodle, only when                      &lt;br /&gt;
// we are looking at the admin settings pages.                                                                                      &lt;br /&gt;
if ($ADMIN-&amp;gt;fulltree) {                                                                                                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Boost provides a nice setting page which splits settings onto separate tabs. We want to use it here.                         &lt;br /&gt;
    $settings = new theme_boost_admin_settingspage_tabs(&#039;themesettingphoto&#039;, get_string(&#039;configtitle&#039;, &#039;theme_photo&#039;));             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Each page is a tab - the first is the &amp;quot;General&amp;quot; tab.                                                                         &lt;br /&gt;
    $page = new admin_settingpage(&#039;theme_photo_general&#039;, get_string(&#039;generalsettings&#039;, &#039;theme_photo&#039;));                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Replicate the preset setting from boost.                                                                                     &lt;br /&gt;
    $name = &#039;theme_photo/preset&#039;;                                                                                                   &lt;br /&gt;
    $title = get_string(&#039;preset&#039;, &#039;theme_photo&#039;);                                                                                   &lt;br /&gt;
    $description = get_string(&#039;preset_desc&#039;, &#039;theme_photo&#039;);                                                                        &lt;br /&gt;
    $default = &#039;default.scss&#039;;                                                                                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // We list files in our own file area to add to the drop down. We will provide our own function to                              &lt;br /&gt;
    // load all the presets from the correct paths.                                                                                 &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
    $files = $fs-&amp;gt;get_area_files($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;itemid, filepath, filename&#039;, false);                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $choices = [];                                                                                                                  &lt;br /&gt;
    foreach ($files as $file) {                                                                                                     &lt;br /&gt;
        $choices[$file-&amp;gt;get_filename()] = $file-&amp;gt;get_filename();                                                                    &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
    // These are the built in presets from Boost.                                                                                   &lt;br /&gt;
    $choices[&#039;default.scss&#039;] = &#039;default.scss&#039;;                                                                                      &lt;br /&gt;
    $choices[&#039;plain.scss&#039;] = &#039;plain.scss&#039;;                                                                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $setting = new admin_setting_configselect($name, $title, $description, $default, $choices);                                     &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Preset files setting.                                                                                                        &lt;br /&gt;
    $name = &#039;theme_photo/presetfiles&#039;;                                                                                              &lt;br /&gt;
    $title = get_string(&#039;presetfiles&#039;,&#039;theme_photo&#039;);                                                                               &lt;br /&gt;
    $description = get_string(&#039;presetfiles_desc&#039;, &#039;theme_photo&#039;);                                                                   &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;preset&#039;, 0,                                         &lt;br /&gt;
        array(&#039;maxfiles&#039; =&amp;gt; 20, &#039;accepted_types&#039; =&amp;gt; array(&#039;.scss&#039;)));                                                               &lt;br /&gt;
    $page-&amp;gt;add($setting);     &lt;br /&gt;
&lt;br /&gt;
    // Variable $brand-color.                                                                                                       &lt;br /&gt;
    // We use an empty default value because the default colour should come from the preset.                                        &lt;br /&gt;
    $name = &#039;theme_photo/brandcolor&#039;;                                                                                               &lt;br /&gt;
    $title = get_string(&#039;brandcolor&#039;, &#039;theme_photo&#039;);                                                                               &lt;br /&gt;
    $description = get_string(&#039;brandcolor_desc&#039;, &#039;theme_photo&#039;);                                                                    &lt;br /&gt;
    $setting = new admin_setting_configcolourpicker($name, $title, $description, &#039;&#039;);                                               &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Must add the page after definiting all the settings!                                                                         &lt;br /&gt;
    $settings-&amp;gt;add($page);                                                                                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Advanced settings.                                                                                                           &lt;br /&gt;
    $page = new admin_settingpage(&#039;theme_photo_advanced&#039;, get_string(&#039;advancedsettings&#039;, &#039;theme_photo&#039;));                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Raw SCSS to include before the content.                                                                                      &lt;br /&gt;
    $setting = new admin_setting_configtextarea(&#039;theme_photo/scsspre&#039;,                                                              &lt;br /&gt;
        get_string(&#039;rawscsspre&#039;, &#039;theme_photo&#039;), get_string(&#039;rawscsspre_desc&#039;, &#039;theme_photo&#039;), &#039;&#039;, PARAM_RAW);                      &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Raw SCSS to include after the content.                                                                                       &lt;br /&gt;
    $setting = new admin_setting_configtextarea(&#039;theme_photo/scss&#039;, get_string(&#039;rawscss&#039;, &#039;theme_photo&#039;),                           &lt;br /&gt;
        get_string(&#039;rawscss_desc&#039;, &#039;theme_photo&#039;), &#039;&#039;, PARAM_RAW);                                                                  &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $settings-&amp;gt;add($page);                                                                                                          &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lang/en/theme_photo.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
// The name of the second tab in the theme settings.                                                                                &lt;br /&gt;
$string[&#039;advancedsettings&#039;] = &#039;Advanced settings&#039;;                                                                                  &lt;br /&gt;
// The brand colour setting.                                                                                                        &lt;br /&gt;
$string[&#039;brandcolor&#039;] = &#039;Brand colour&#039;;                                                                                             &lt;br /&gt;
// The brand colour setting description.                                                                                            &lt;br /&gt;
$string[&#039;brandcolor_desc&#039;] = &#039;The accent colour.&#039;;     &lt;br /&gt;
// A description shown in the admin theme selector.                                                                                 &lt;br /&gt;
$string[&#039;choosereadme&#039;] = &#039;Theme photo is a child theme of Boost. It adds the ability to upload background photos.&#039;;                &lt;br /&gt;
// Name of the settings pages.                                                                                                      &lt;br /&gt;
$string[&#039;configtitle&#039;] = &#039;Photo settings&#039;;                                                                                          &lt;br /&gt;
// Name of the first settings tab.                                                                                                  &lt;br /&gt;
$string[&#039;generalsettings&#039;] = &#039;General settings&#039;;                                                                                    &lt;br /&gt;
// The name of our plugin.                                                                                                          &lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Photo&#039;;                                                                                                    &lt;br /&gt;
// Preset files setting.                                                                                                            &lt;br /&gt;
$string[&#039;presetfiles&#039;] = &#039;Additional theme preset files&#039;;                                                                           &lt;br /&gt;
// Preset files help text.                                                                                                          &lt;br /&gt;
$string[&#039;presetfiles_desc&#039;] = &#039;Preset files can be used to dramatically alter the appearance of the theme. See &amp;lt;a href=https://docs.moodle.org/dev/Boost_Presets&amp;gt;Boost presets&amp;lt;/a&amp;gt; for information on creating and sharing your own preset files, and see the &amp;lt;a href=http://moodle.net/boost&amp;gt;Presets repository&amp;lt;/a&amp;gt; for presets that others have shared.&#039;;&lt;br /&gt;
// Preset setting.                                                                                                                  &lt;br /&gt;
$string[&#039;preset&#039;] = &#039;Theme preset&#039;;                                                                                                 &lt;br /&gt;
// Preset help text.                                                                                                                &lt;br /&gt;
$string[&#039;preset_desc&#039;] = &#039;Pick a preset to broadly change the look of the theme.&#039;;                                                  &lt;br /&gt;
// Raw SCSS setting.                                                                                                                &lt;br /&gt;
$string[&#039;rawscss&#039;] = &#039;Raw SCSS&#039;;                                                                                                    &lt;br /&gt;
// Raw SCSS setting help text.                                                                                                      &lt;br /&gt;
$string[&#039;rawscss_desc&#039;] = &#039;Use this field to provide SCSS or CSS code which will be injected at the end of the style sheet.&#039;;       &lt;br /&gt;
// Raw initial SCSS setting.                                                                                                        &lt;br /&gt;
$string[&#039;rawscsspre&#039;] = &#039;Raw initial SCSS&#039;;                                                                                         &lt;br /&gt;
// Raw initial SCSS setting help text.                                                                                              &lt;br /&gt;
$string[&#039;rawscsspre_desc&#039;] = &#039;In this field you can provide initialising SCSS code, it will be injected before everything else. Most of the time you will use this setting to define variables.&#039;;&lt;br /&gt;
// We need to include a lang string for each block region.                                                                          &lt;br /&gt;
$string[&#039;region-side-pre&#039;] = &#039;Right&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We aren&#039;t quite there yet as you will notice if you try and upload a preset file and then choose it. The &amp;quot;theme_boost_get_main_scss_content&amp;quot; function from Boost is expecting the preset files to be stored in a file area for theme_boost only. We need to add this function to our own theme and tweak it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is the function that returns the SCSS source for the main file in our theme. We override the boost version because          &lt;br /&gt;
// we want to allow presets uploaded to our own theme file area to be selected in the preset list.                                  &lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {                                                                                                   &lt;br /&gt;
    return theme_photo_get_main_scss_content($theme);                                                                               &lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        // This preset file was fetched from the file area for theme_photo and not theme_boost (see the line above).                &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}             &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Stop and try it out ===&lt;br /&gt;
So now what is working and what isn&#039;t. Well - everything should be working and you should have a nice new theme extending boost with it&#039;s own settings pages. When Boost gets updates for bug fixes your new theme will inherit those fixes as it inherits all the SCSS and templates from theme boost. In addition your new theme will accept preset files and supports all the same features and settings as boost, ready to add more.&lt;br /&gt;
&lt;br /&gt;
== Take it further ==&lt;br /&gt;
Now we have our very nice starting point we can start changing or adding features, customising templates and output or tweaking the SCSS.&lt;br /&gt;
&lt;br /&gt;
=== Add some new settings ===&lt;br /&gt;
&lt;br /&gt;
From this point in the tutorial we will start adding features to our theme to extend it and make it AWESOME!&lt;br /&gt;
&lt;br /&gt;
Lets start with a new setting to set a background image on the login page. As you saw earlier, our theme defines it&#039;s list of settings in a file called settings.php. See [[Admin settings]] for more information about adding admin settings to any plugin. All of the different kinds of admin settings can be found in lib/adminlib.php. In our case we will want to add a setting which allows an admin to upload an image file. This is an &amp;quot;admin_setting_configstoredfile&amp;quot; and we add it to our theme by adding this code to the settings.php file inside and at the end of the &amp;quot;if ($ADMIN-&amp;gt;fulltree) {&amp;quot; condition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    // Login page background setting.                                                                                               &lt;br /&gt;
    // We use variables for readability.                                                                                            &lt;br /&gt;
    $name = &#039;theme_photo/loginbackgroundimage&#039;;                                                                                     &lt;br /&gt;
    $title = get_string(&#039;loginbackgroundimage&#039;, &#039;theme_photo&#039;);                                                                     &lt;br /&gt;
    $description = get_string(&#039;loginbackgroundimage_desc&#039;, &#039;theme_photo&#039;);                                                          &lt;br /&gt;
    // This creates the new setting.                                                                                                &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;loginbackgroundimage&#039;);                             &lt;br /&gt;
    // This means that theme caches will automatically be cleared when this setting is changed.                                     &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    // We always have to add the setting to a page for it to have any effect.                                                       &lt;br /&gt;
    $page-&amp;gt;add($setting);       &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need to add new lang strings to our language file.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lang/en/theme_photo.php&amp;quot;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Background image for login page.                                                                                                 &lt;br /&gt;
$string[&#039;loginbackgroundimage&#039;] = &#039;Login page background image&#039;;                                                                    &lt;br /&gt;
// Background image for login page.                                                                                                 &lt;br /&gt;
$string[&#039;loginbackgroundimage_desc&#039;] = &#039;An image that will be stretched to fill the background of the login page.&#039;;                 &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have a new setting that lets us upload a file - but it doesn&#039;t actually do anything yet. We need to update the theme to set this image background on the login page.&lt;br /&gt;
&lt;br /&gt;
In order to change the SCSS for our theme we will add 2 additional SCSS files and include them before and after our main scss.&lt;br /&gt;
&lt;br /&gt;
We already have a function in our lib.php file which fetches the main SCSS for our theme. This is a good point to include additional SCSS files. We can add 2 lines to the end of this function to achieve this.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        // This preset file was fetched from the file area for theme_photo and not theme_boost (see the line above).                &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Pre CSS - this is loaded AFTER any prescss from the setting but before the main scss.                                        &lt;br /&gt;
    $pre = file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/photo/scss/pre.scss&#039;);                                                         &lt;br /&gt;
    // Post CSS - this is loaded AFTER the main scss but before the extra scss from the setting.                                    &lt;br /&gt;
    $post = file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/photo/scss/post.scss&#039;);                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Combine them together.                                                                                                       &lt;br /&gt;
    return $pre . &amp;quot;\n&amp;quot; . $scss . &amp;quot;\n&amp;quot; . $post;                                                                                      &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;scss/pre.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
// Pre SCSS for the theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;scss/post.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
// Post SCSS for the theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Why do we use pre and post SCSS? ====&lt;br /&gt;
SCSS/SASS is a powerful language for creating CSS. It supports variables, functions, loops just like php. For lots of information and an introduction to SCSS read about [https://en.wikipedia.org/wiki/Sass_(stylesheet_language) Sass on wikipedia]. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pre SCSS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In Boost we use many variables when creating style rules.&lt;br /&gt;
&lt;br /&gt;
When declaring a variable in SCSS - it is best practice to define it like this:&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
$mycoolcolour: #FF0 !default;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this means is - if this variable is not defined already - set it to the hex value &#039;#FF0&#039;;&lt;br /&gt;
&lt;br /&gt;
So by setting this variable in some PRE scss we can override the default value of this variable everywhere it is used. Boost is built with the [https://v4-alpha.getbootstrap.com/ Bootstrap 4 (Alpha 4)] CSS Framework. This is a framework which uses SCSS to provide many extremely useful layouts and components which can be reused without adding specific CSS rules to style every page. Because bootstrap consistently uses variables we can customise many of these components easily by setting the value of the variables before we include the Bootstrap SCSS files.&lt;br /&gt;
&lt;br /&gt;
Many variables are available in /theme/boost/scss/bootstrap/_variables.scss - as an example we can change the look of all buttons and input fields with this one variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
$border-radius: 8px;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Post SCSS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Post SCSS is useful for defining full CSS rules. Because they are included last, they override any previous matching selector with the same [https://en.wikipedia.org/wiki/Cascading_Style_Sheets#Specificity Specificity].&lt;br /&gt;
&lt;br /&gt;
=== Tips for customising Moodle with SCSS (or CSS) ===&lt;br /&gt;
Some handy things to know when you are new to theming is that Moodle adds some classes to every page that helps you target a specific page or set of pages with some style rules. &lt;br /&gt;
&lt;br /&gt;
If you inspect a moodle page and look at the body tag you will see a long list of classes e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code html&amp;gt;&lt;br /&gt;
&amp;lt;body id=&amp;quot;page-course-view-weeks&amp;quot; class=&amp;quot;format-weeks  path-course path-course-view safari dir-ltr lang-en yui-skin-sam yui3-skin-sam damyon-per-in-moodle-com--stable_master pagelayout-course course-11 context-497 category-1 drawer-open-left jsenabled&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can see from this example that each page gets an id. This is a simplified representation of the current page in the navigation. In this example we are looking at the course page and this course is using the weeks format. &lt;br /&gt;
&lt;br /&gt;
The classes on the body tag can also be used to target a page or set of pages.&lt;br /&gt;
* &amp;lt;code&amp;gt;format-weeks&amp;lt;/code&amp;gt; The course format&lt;br /&gt;
* &amp;lt;code&amp;gt;path-course path-course-view&amp;lt;/code&amp;gt; The parts of the bread-crumb leading up to the current page (The current page is what goes in the id)&lt;br /&gt;
* &amp;lt;code&amp;gt;safari&amp;lt;/code&amp;gt; Some server side guessing of the browser type - it&#039;s not accurate so I would not rely on it&lt;br /&gt;
* &amp;lt;code&amp;gt;dir-ltr&amp;lt;/code&amp;gt; The direction of the current language for the page ( dir-rtl for RTL languages )&lt;br /&gt;
* &amp;lt;code&amp;gt;lang-en&amp;lt;/code&amp;gt; The current language of the page&lt;br /&gt;
* &amp;lt;code&amp;gt;yui*&amp;lt;/code&amp;gt; Legacy yui classes - ignore these&lt;br /&gt;
* &amp;lt;code&amp;gt;damyon-per-in-moodle-com--stable_master&amp;lt;/code&amp;gt; The current hostname for the site + the site name&lt;br /&gt;
* &amp;lt;code&amp;gt;pagelayout-course&amp;lt;/code&amp;gt; The layout type for the current page&lt;br /&gt;
* &amp;lt;code&amp;gt;course-11&amp;lt;/code&amp;gt; The id of the current course&lt;br /&gt;
* &amp;lt;code&amp;gt;context-497&amp;lt;/code&amp;gt; The current context id&lt;br /&gt;
* &amp;lt;code&amp;gt;category-1&amp;lt;/code&amp;gt; The category for the current course&lt;br /&gt;
* &amp;lt;code&amp;gt;drawer-open-left&amp;lt;/code&amp;gt; Added / removed when the navigation drawer is opened / closed in Boost&lt;br /&gt;
* &amp;lt;code&amp;gt;jsenabled&amp;lt;/code&amp;gt; True if the browser supports javascript&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/dev/Themes_overview#.3Cbody.3E_CSS_id_and_classes Read about Body id and classes].&lt;br /&gt;
&lt;br /&gt;
In our example the page layout is the most useful here as we have a specific page layout for login pages. We can now craft a rule that applies a background image only to login pages using &amp;quot;body.pagelayout-login&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How do we refer to an image in SCSS ? ===&lt;br /&gt;
So now we can add a rule to the post.scss which will set the background image for the login page. First we need to know how to construct a url to the background images from our stylesheet. &lt;br /&gt;
&lt;br /&gt;
In stylesheets in Moodle we can use a special pix tag to refer to images from our theme. The rule to attach the background image looks like this:&lt;br /&gt;
&#039;&#039;scss/post.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
body.pagelayout-login {                                                                                                             &lt;br /&gt;
    background-image: url([[pix:theme_photo|loginbackgroundimage]]);                                                                &lt;br /&gt;
    background-size: cover;                                                                                                         &lt;br /&gt;
}                          &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are 2 important parts to this tag (the bit in square brackets). The first is &amp;quot;theme_photo&amp;quot;. In this case we are passing a component name, the image serving code in theme_config::resolve_image_location() will then look for an image file in several locations. One of these is in &amp;quot;$CFG-&amp;gt;dataroot/pix_plugins/$type/$plugin/$image&amp;quot;. We can use this to make sure the image gets served correctly by copying the file saved in the setting to this location every time it is updated. (There is an alterative way we could do this by implementing pluginfile.php in our theme - which you can read about in the [[File API]] ).&lt;br /&gt;
&lt;br /&gt;
If we had just passed the value &amp;quot;theme&amp;quot; the image serving code would have looked for the image in the &amp;quot;pix&amp;quot; folder of our theme.&lt;br /&gt;
&lt;br /&gt;
So - we need this final change to copy the image file into our dataroot each time the setting is changed.&lt;br /&gt;
&lt;br /&gt;
In the settings file we will update the callback to a new function which we will define in our lib.php.&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Login page background setting.                                                                                               &lt;br /&gt;
    // We use variables for readability.                                                                                            &lt;br /&gt;
    $name = &#039;theme_photo/loginbackgroundimage&#039;;                                                                                     &lt;br /&gt;
    $title = get_string(&#039;loginbackgroundimage&#039;, &#039;theme_photo&#039;);                                                                     &lt;br /&gt;
    $description = get_string(&#039;loginbackgroundimage_desc&#039;, &#039;theme_photo&#039;);                                                          &lt;br /&gt;
    // This creates the new setting.                                                                                                &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;loginbackgroundimage&#039;);                             &lt;br /&gt;
    // This function will copy the image into the data_root location it can be served from.                                         &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_photo_update_settings_images&#039;);                                                            &lt;br /&gt;
    // We always have to add the setting to a page for it to have any effect.                                                       &lt;br /&gt;
    $page-&amp;gt;add($setting);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_update_settings_images($settingname) {                                                                         &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // The setting name that was updated comes as a string like &#039;s_theme_photo_loginbackgroundimage&#039;.                               &lt;br /&gt;
    // We split it on &#039;_&#039; characters.                                                                                               &lt;br /&gt;
    $parts = explode(&#039;_&#039;, $settingname);                                                                                            &lt;br /&gt;
    // And get the last one to get the setting name..                                                                               &lt;br /&gt;
    $settingname = end($parts);                                                                                                     &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Admin settings are stored in system context.                                                                                 &lt;br /&gt;
    $syscontext = context_system::instance();                                                                                       &lt;br /&gt;
    // This is the component name the setting is stored in.                                                                         &lt;br /&gt;
    $component = &#039;theme_photo&#039;;                                                                                                     &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // This is the value of the admin setting which is the filename of the uploaded file.                                           &lt;br /&gt;
    $filename = get_config($component, $settingname);                                                                               &lt;br /&gt;
    // We extract the file extension because we want to preserve it.                                                                &lt;br /&gt;
    $extension = substr($filename, strrpos($filename, &#039;.&#039;) + 1);                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // This is the path in the moodle internal file system.                                                                         &lt;br /&gt;
    $fullpath = &amp;quot;/{$syscontext-&amp;gt;id}/{$component}/{$settingname}/0{$filename}&amp;quot;;                                                      &lt;br /&gt;
    // Get an instance of the moodle file storage.                                                                                  &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
    // This is an efficient way to get a file if we know the exact path.                                                            &lt;br /&gt;
    if ($file = $fs-&amp;gt;get_file_by_hash(sha1($fullpath))) {                                                                           &lt;br /&gt;
        // We got the stored file - copy it to dataroot.                                                                            &lt;br /&gt;
        // This location matches the searched for location in theme_config::resolve_image_location.                                 &lt;br /&gt;
        $pathname = $CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039; . $settingname . &#039;.&#039; . $extension;                                 &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // This pattern matches any previous files with maybe different file extensions.                                            &lt;br /&gt;
        $pathpattern = $CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039; . $settingname . &#039;.*&#039;;                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Make sure this dir exists.                                                                                               &lt;br /&gt;
        @mkdir($CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039;, $CFG-&amp;gt;directorypermissions, true);                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Delete any existing files for this setting.                                                                              &lt;br /&gt;
        foreach (glob($pathpattern) as $filename) {                                                                                 &lt;br /&gt;
            @unlink($filename);                                                                                                     &lt;br /&gt;
        }                                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Copy the current file to this location.                                                                                  &lt;br /&gt;
        $file-&amp;gt;copy_content_to($pathname);                                                                                          &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Reset theme caches.                                                                                                          &lt;br /&gt;
    theme_reset_all_caches();                                                                                                       &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I won&#039;t show it here - but it is now easy to add a new background image setting for every layout type. I can re-use this theme_photo_update_settings_images callback for each one - so all I have to do is add the setting to the settings.php file, add the SCSS rule to the scss/post.scss file and add the lang strings to the language file.&lt;br /&gt;
&lt;br /&gt;
Thats it for this tutorial, but there are [[:Category:Themes| more Themes docs]] to browse.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Themes]]&lt;/div&gt;</summary>
		<author><name>Meeth</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Creating_a_theme_based_on_boost&amp;diff=57738</id>
		<title>Creating a theme based on boost</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Creating_a_theme_based_on_boost&amp;diff=57738"/>
		<updated>2020-07-31T09:45:53Z</updated>

		<summary type="html">&lt;p&gt;Meeth: Undo revision 57737 by Meeth (talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 3.2}}&lt;br /&gt;
{{Template:Themes}}&lt;br /&gt;
&lt;br /&gt;
This is a tutorial for how to create a new theme in any version of Moodle from 3.2 and later.&lt;br /&gt;
&lt;br /&gt;
Moodle 3.2 introduced a new core theme named &amp;quot;Boost&amp;quot; which is a great starting point for themers wanting to build a modern Moodle theme utilising all the latest features available to themes in Moodle.  If you aren&#039;t sure where to start, then START HERE!  :-)&lt;br /&gt;
&lt;br /&gt;
== Getting started ==&lt;br /&gt;
What is a theme? A theme in Moodle is just another type of plugin that can be developed. Themes are responsible for setting up the structure of each page and have the ability to customise the output of any page in Moodle.&lt;br /&gt;
&lt;br /&gt;
This tutorial is based on a working theme named &amp;quot;theme_photo&amp;quot; you can download it or view the source code for it here: https://github.com/damyon/moodle-theme_photo&lt;br /&gt;
&lt;br /&gt;
=== Choosing a name ===&lt;br /&gt;
Your new theme will need a name. Try and think of something short and memorable - and make sure it is not a name that has already been used by someone else. A quick search on the moodle.org/plugins can save you a lot of work renaming things later.&lt;br /&gt;
&lt;br /&gt;
Lets call our new example theme &amp;quot;photo&amp;quot; as we will add some settings to allow &amp;quot;photos&amp;quot; in various places in Moodle.&lt;br /&gt;
&lt;br /&gt;
=== Starting files ===&lt;br /&gt;
As a plugin, themes must start with the basic structure of a plugin in Moodle. See https://docs.moodle.org/dev/Tutorial#The_skeleton_of_your_plugin for an overview of the files common to all plugins in Moodle.&lt;br /&gt;
&lt;br /&gt;
Following this guide we can start creating our theme. First we create the folder for the new theme under &amp;quot;/theme/&amp;quot; folder in the Moodle root directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
/theme/photo/&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we need to add some standard plugin files to our theme. First is version.php&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/theme/photo/version.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the version of the plugin.                                                                                               &lt;br /&gt;
$plugin-&amp;gt;version = &#039;2016102100&#039;;                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the version of Moodle this plugin requires.                                                                              &lt;br /&gt;
$plugin-&amp;gt;requires = &#039;2016070700&#039;;                                                                                                   &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the component name of the plugin - it always starts with &#039;theme_&#039;                                                        &lt;br /&gt;
// for themes and should be the same as the name of the folder.                                                                     &lt;br /&gt;
$plugin-&amp;gt;component = &#039;theme_photo&#039;;                                                                                                 &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a list of plugins, this plugin depends on (and their versions).                                                          &lt;br /&gt;
$plugin-&amp;gt;dependencies = [                                                                                                           &lt;br /&gt;
    &#039;theme_boost&#039; =&amp;gt; &#039;2016102100&#039;                                                                                                   &lt;br /&gt;
];                                                                              &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need a language file so that all our strings can be translated into different languages. The name of this file is the component name of our plugin and it sits in the lang/en/ folder for our plugin. We can include translations of our plugin, but we can also provide translations via the https://lang.moodle.org/ website once our plugin has been published to the plugins database at http://www.moodle.org/plugins/.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/theme/photo/lang/en/theme_photo.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// A description shown in the admin theme selector.                                                                                 &lt;br /&gt;
$string[&#039;choosereadme&#039;] = &#039;Theme photo is a child theme of Boost. It adds the ability to upload background photos.&#039;;                &lt;br /&gt;
// The name of our plugin.                                                                                                          &lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Photo&#039;;                                                                                                    &lt;br /&gt;
// We need to include a lang string for each block region.                                                                          &lt;br /&gt;
$string[&#039;region-side-pre&#039;] = &#039;Right&#039;;                                         &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Theme specific files ===&lt;br /&gt;
Theme plugins have a few more standard files they need to define. &lt;br /&gt;
&lt;br /&gt;
Themes require a favicon file to show in the address bar. See [[http://docs.moodle.org/en/Favicon Favicon]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;pix/favicon.ico&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(Image file not shown).&lt;br /&gt;
&lt;br /&gt;
Themes also require an example screenshot to be displayed in the theme selector.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;pix/screenshot.jpg&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(Image file not shown).&lt;br /&gt;
&lt;br /&gt;
Themes require a lib.php file. This file contains callbacks used by various API&#039;s in Moodle. Initially this file can be empty, but as we add features to our theme we will need to add some functions here.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
// We will add callbacks here as we add features to our theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Theme config goes in a config.php file. This is one of the most important files in our theme. Once we add this file we will be ready to test our theme for the first time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
// $THEME is defined before this page is included and we can define settings by adding properties to this global object.            &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// The first setting we need is the name of the theme. This should be the last part of the component name, and the same             &lt;br /&gt;
// as the directory name for our theme.                                                                                             &lt;br /&gt;
$THEME-&amp;gt;name = &#039;photo&#039;;                                                                                                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This setting list the style sheets we want to include in our theme. Because we want to use SCSS instead of CSS - we won&#039;t        &lt;br /&gt;
// list any style sheets. If we did we would list the name of a file in the /style/ folder for our theme without any css file      &lt;br /&gt;
// extensions.                                                                                                                      &lt;br /&gt;
$THEME-&amp;gt;sheets = [];                                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a setting that can be used to provide some styling to the content in the TinyMCE text editor. This is no longer the      &lt;br /&gt;
// default text editor and &amp;quot;Atto&amp;quot; does not need this setting so we won&#039;t provide anything. If we did it would work the same         &lt;br /&gt;
// as the previous setting - listing a file in the /styles/ folder.                                                                 &lt;br /&gt;
$THEME-&amp;gt;editor_sheets = [];                                                                                                         &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a critical setting. We want to inherit from theme_boost because it provides a great starting point for SCSS bootstrap4   &lt;br /&gt;
// themes. We could add more than one parent here to inherit from multiple parents, and if we did they would be processed in        &lt;br /&gt;
// order of importance (later themes overriding earlier ones). Things we will inherit from the parent theme include                 &lt;br /&gt;
// styles and mustache templates and some (not all) settings.                                                                       &lt;br /&gt;
$THEME-&amp;gt;parents = [&#039;boost&#039;];                                                                                                        &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// A dock is a way to take blocks out of the page and put them in a persistent floating area on the side of the page. Boost         &lt;br /&gt;
// does not support a dock so we won&#039;t either - but look at bootstrapbase for an example of a theme with a dock.                    &lt;br /&gt;
$THEME-&amp;gt;enable_dock = false;                                                                                                        &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is an old setting used to load specific CSS for some YUI JS. We don&#039;t need it in Boost based themes because Boost           &lt;br /&gt;
// provides default styling for the YUI modules that we use. It is not recommended to use this setting anymore.                     &lt;br /&gt;
$THEME-&amp;gt;yuicssmodules = array();                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// Most themes will use this rendererfactory as this is the one that allows the theme to override any other renderer.               &lt;br /&gt;
$THEME-&amp;gt;rendererfactory = &#039;theme_overridden_renderer_factory&#039;;                                                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a list of blocks that are required to exist on all pages for this theme to function correctly. For example               &lt;br /&gt;
// bootstrap base requires the settings and navigation blocks because otherwise there would be no way to navigate to all the        &lt;br /&gt;
// pages in Moodle. Boost does not require these blocks because it provides other ways to navigate built into the theme.            &lt;br /&gt;
$THEME-&amp;gt;requiredblocks = &#039;&#039;;   &lt;br /&gt;
&lt;br /&gt;
// This is a feature that tells the blocks library not to use the &amp;quot;Add a block&amp;quot; block. We don&#039;t want this in boost based themes because&lt;br /&gt;
// it forces a block region into the page when editing is enabled and it takes up too much room.&lt;br /&gt;
$THEME-&amp;gt;addblockposition = BLOCK_ADDBLOCK_POSITION_FLATNAV;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ready set go! ===&lt;br /&gt;
If you have been following along - now we are at the point where we can actually install and test our new theme. Try it now by visiting the admin notifications page to install the new plugin, and then choosing the new theme from the theme selector.&lt;br /&gt;
&lt;br /&gt;
[[https://docs.moodle.org/en/Standard_themes#Theme_selector Theme selector]]&lt;br /&gt;
&lt;br /&gt;
When you choose the new theme - you will find that it looks exactly the same as Boost. At this point with our minimal configuration - we are inheriting almost everything from our parent theme including styles and templates. You will notice though that we don&#039;t inherit the settings from our parent theme. If you choose a different preset in Boost - it is not applied in this child theme.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&lt;br /&gt;
Note: make sure your config.php file contains $THEME-&amp;gt;hidefromselector = false; (or at least set to false) or else, your theme wont show up in theme selector.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What if I want the settings too? ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&lt;br /&gt;
This section is included for completeness - but it is not recommended for themes to utilise settings from their parents. To find out how to duplicate the settings from the parent theme so they operate independently skip to [[#Duplicate the settings from Boost]].&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If I want the settings from Boost to apply to my child theme as well I need to know a bit about how each of the settings in Boost is applied to make them work in my child theme.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Setting 1 - preset.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;preset&amp;quot; file is the file that is used as the main file for scss compilation. In Boost this is controlled by the theme config value:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {&lt;br /&gt;
    return theme_boost_get_main_scss_content($theme);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_boost&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this function is doing is checking for a theme setting &amp;quot;preset&amp;quot; and either fetching the file from Moodles internal file storage, or from the /preset/ folder. The function then returns the contents of this file.&lt;br /&gt;
&lt;br /&gt;
It does not automatically work for our child theme because we have no setting named &amp;quot;preset&amp;quot; in our child theme and this code is not searching the theme parents for the setting. If we wanted it to apply we could do this in our child theme:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This setting defines the main scss file for our theme to be compiled. We could set it to a static file in the scss folder or to a function which returns the SCSS based on theme settings.&lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {&lt;br /&gt;
&lt;br /&gt;
    // We need to load the config for our parent theme because that is where the preset setting is defined.&lt;br /&gt;
    $parentconfig = theme_config::load(&#039;boost&#039;);&lt;br /&gt;
    // Call a function from our parent themes lib.php file to fetch the content of the themes main SCSS file based on it&#039;s own config, not ours.&lt;br /&gt;
    return theme_boost_get_main_scss_content($parentconfig);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings 2+3 brandcolor + scsspre&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The way these settings work is they generate a chunk of SCSS to be prepended to the main scss file. In boost they work like this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;prescsscallback = &#039;theme_boost_get_pre_scss&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_pre_scss($theme) {                                                                                         &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $configurable = [                                                                                                               &lt;br /&gt;
        // Config key =&amp;gt; [variableName, ...].                                                                                       &lt;br /&gt;
        &#039;brandcolor&#039; =&amp;gt; [&#039;brand-primary&#039;],                                                                                          &lt;br /&gt;
    ];                                                                                                                              &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Prepend variables first.                                                                                                     &lt;br /&gt;
    foreach ($configurable as $configkey =&amp;gt; $targets) {                                                                             &lt;br /&gt;
        $value = isset($theme-&amp;gt;settings-&amp;gt;{$configkey}) ? $theme-&amp;gt;settings-&amp;gt;{$configkey} : null;                                     &lt;br /&gt;
        if (empty($value)) {                                                                                                        &lt;br /&gt;
            continue;                                                                                                               &lt;br /&gt;
        }                                                                                                                           &lt;br /&gt;
        array_map(function($target) use (&amp;amp;$scss, $value) {                                                                          &lt;br /&gt;
            $scss .= &#039;$&#039; . $target . &#039;: &#039; . $value . &amp;quot;;\n&amp;quot;;                                                                         &lt;br /&gt;
        }, (array) $targets);                                                                                                       &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Prepend pre-scss.                                                                                                            &lt;br /&gt;
    if (!empty($theme-&amp;gt;settings-&amp;gt;scsspre)) {                                                                                        &lt;br /&gt;
        $scss .= $theme-&amp;gt;settings-&amp;gt;scsspre;                                                                                         &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}  &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this code is doing is: &lt;br /&gt;
* looping over a list of theme settings that map to a SCSS variable and building some SCSS to initialise that variable from the setting. In Boost there is only one * brandprimary - but if we wanted to expose more bootstrap variables as theme settings we could use this function as a template in our child theme and add more settings to the $configurable array.&lt;br /&gt;
* Adding all of the raw SCSS from the scsspre theme setting&lt;br /&gt;
* Returning the whole thing as a string to be added before the main scss file.&lt;br /&gt;
&lt;br /&gt;
If we want this code to work in our child theme, using the settings from Boost we could do this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is a function that returns some SCSS as a string to prepend to the main SCSS file.                                          &lt;br /&gt;
$THEME-&amp;gt;prescsscallback = &#039;theme_photo_get_pre_scss&#039;;               &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Function to return the SCSS to prepend to our main SCSS for this theme.&lt;br /&gt;
// Note the function name starts with the component name because this is a global function and we don&#039;t want namespace clashes.&lt;br /&gt;
function theme_photo_get_pre_scss($theme) {&lt;br /&gt;
    // Load the settings from the parent.                                                                                           &lt;br /&gt;
    $theme = theme_config::load(&#039;boost&#039;);                                                                                           &lt;br /&gt;
    // Call the parent themes get_pre_scss function.                                                                                &lt;br /&gt;
    return theme_boost_get_pre_scss($theme);                         &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Setting 4 scss (post)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The final setting from Boost is a raw text field which adds SCSS to the end of the main SCSS file. This is a useful place to add style rules as they will override previously defined styles with the same specificity. It is applied in Boost by the following lines:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;extrascsscallback = &#039;theme_boost_get_extra_scss&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_extra_scss($theme) {                                                                                       &lt;br /&gt;
    return !empty($theme-&amp;gt;settings-&amp;gt;scss) ? $theme-&amp;gt;settings-&amp;gt;scss : &#039;&#039;;                                                            &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is just returning the value of the setting as a string.&lt;br /&gt;
&lt;br /&gt;
To make this setting apply in our child theme too - we use similar code to the previous sections.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is a function that returns some SCSS as a string to append to the main SCSS file.                                          &lt;br /&gt;
$THEME-&amp;gt;extrascsscallback = &#039;theme_photo_get_extra_scss&#039;;               &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Function to return the SCSS to append to our main SCSS for this theme.&lt;br /&gt;
// Note the function name starts with the component name because this is a global function and we don&#039;t want namespace clashes.&lt;br /&gt;
function theme_photo_get_extra_scss($theme) {&lt;br /&gt;
    // Load the settings from the parent.                                                                                           &lt;br /&gt;
    $theme = theme_config::load(&#039;boost&#039;);                                                                                           &lt;br /&gt;
    // Call the parent themes get_extra_scss function.                                                                                &lt;br /&gt;
    return theme_boost_get_extra_scss($theme);                         &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Duplicate the settings from Boost  ===&lt;br /&gt;
&lt;br /&gt;
This is the recommended way to extend boost as your child theme will not be affected by changes to the Boost settings, and both themes can be in use with different settings applied.&lt;br /&gt;
&lt;br /&gt;
All that needs to happen is to create theme settings in the child theme that match each of the settings in the parent theme. You will need to add matching language strings for each of these settings in the language file.&lt;br /&gt;
&lt;br /&gt;
This example shows how to do it - We are re-using the nice looking theme_boost_admin_settingspage_tabs class from boost and creating duplicate versions of each of the settings.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is used for performance, we don&#039;t need to know about these settings on every page in Moodle, only when                      &lt;br /&gt;
// we are looking at the admin settings pages.                                                                                      &lt;br /&gt;
if ($ADMIN-&amp;gt;fulltree) {                                                                                                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Boost provides a nice setting page which splits settings onto separate tabs. We want to use it here.                         &lt;br /&gt;
    $settings = new theme_boost_admin_settingspage_tabs(&#039;themesettingphoto&#039;, get_string(&#039;configtitle&#039;, &#039;theme_photo&#039;));             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Each page is a tab - the first is the &amp;quot;General&amp;quot; tab.                                                                         &lt;br /&gt;
    $page = new admin_settingpage(&#039;theme_photo_general&#039;, get_string(&#039;generalsettings&#039;, &#039;theme_photo&#039;));                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Replicate the preset setting from boost.                                                                                     &lt;br /&gt;
    $name = &#039;theme_photo/preset&#039;;                                                                                                   &lt;br /&gt;
    $title = get_string(&#039;preset&#039;, &#039;theme_photo&#039;);                                                                                   &lt;br /&gt;
    $description = get_string(&#039;preset_desc&#039;, &#039;theme_photo&#039;);                                                                        &lt;br /&gt;
    $default = &#039;default.scss&#039;;                                                                                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // We list files in our own file area to add to the drop down. We will provide our own function to                              &lt;br /&gt;
    // load all the presets from the correct paths.                                                                                 &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
    $files = $fs-&amp;gt;get_area_files($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;itemid, filepath, filename&#039;, false);                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $choices = [];                                                                                                                  &lt;br /&gt;
    foreach ($files as $file) {                                                                                                     &lt;br /&gt;
        $choices[$file-&amp;gt;get_filename()] = $file-&amp;gt;get_filename();                                                                    &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
    // These are the built in presets from Boost.                                                                                   &lt;br /&gt;
    $choices[&#039;default.scss&#039;] = &#039;default.scss&#039;;                                                                                      &lt;br /&gt;
    $choices[&#039;plain.scss&#039;] = &#039;plain.scss&#039;;                                                                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $setting = new admin_setting_configselect($name, $title, $description, $default, $choices);                                     &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Preset files setting.                                                                                                        &lt;br /&gt;
    $name = &#039;theme_photo/presetfiles&#039;;                                                                                              &lt;br /&gt;
    $title = get_string(&#039;presetfiles&#039;,&#039;theme_photo&#039;);                                                                               &lt;br /&gt;
    $description = get_string(&#039;presetfiles_desc&#039;, &#039;theme_photo&#039;);                                                                   &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;preset&#039;, 0,                                         &lt;br /&gt;
        array(&#039;maxfiles&#039; =&amp;gt; 20, &#039;accepted_types&#039; =&amp;gt; array(&#039;.scss&#039;)));                                                               &lt;br /&gt;
    $page-&amp;gt;add($setting);     &lt;br /&gt;
&lt;br /&gt;
    // Variable $brand-color.                                                                                                       &lt;br /&gt;
    // We use an empty default value because the default colour should come from the preset.                                        &lt;br /&gt;
    $name = &#039;theme_photo/brandcolor&#039;;                                                                                               &lt;br /&gt;
    $title = get_string(&#039;brandcolor&#039;, &#039;theme_photo&#039;);                                                                               &lt;br /&gt;
    $description = get_string(&#039;brandcolor_desc&#039;, &#039;theme_photo&#039;);                                                                    &lt;br /&gt;
    $setting = new admin_setting_configcolourpicker($name, $title, $description, &#039;&#039;);                                               &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Must add the page after definiting all the settings!                                                                         &lt;br /&gt;
    $settings-&amp;gt;add($page);                                                                                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Advanced settings.                                                                                                           &lt;br /&gt;
    $page = new admin_settingpage(&#039;theme_photo_advanced&#039;, get_string(&#039;advancedsettings&#039;, &#039;theme_photo&#039;));                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Raw SCSS to include before the content.                                                                                      &lt;br /&gt;
    $setting = new admin_setting_configtextarea(&#039;theme_photo/scsspre&#039;,                                                              &lt;br /&gt;
        get_string(&#039;rawscsspre&#039;, &#039;theme_photo&#039;), get_string(&#039;rawscsspre_desc&#039;, &#039;theme_photo&#039;), &#039;&#039;, PARAM_RAW);                      &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Raw SCSS to include after the content.                                                                                       &lt;br /&gt;
    $setting = new admin_setting_configtextarea(&#039;theme_photo/scss&#039;, get_string(&#039;rawscss&#039;, &#039;theme_photo&#039;),                           &lt;br /&gt;
        get_string(&#039;rawscss_desc&#039;, &#039;theme_photo&#039;), &#039;&#039;, PARAM_RAW);                                                                  &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $settings-&amp;gt;add($page);                                                                                                          &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lang/en/theme_photo.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
// The name of the second tab in the theme settings.                                                                                &lt;br /&gt;
$string[&#039;advancedsettings&#039;] = &#039;Advanced settings&#039;;                                                                                  &lt;br /&gt;
// The brand colour setting.                                                                                                        &lt;br /&gt;
$string[&#039;brandcolor&#039;] = &#039;Brand colour&#039;;                                                                                             &lt;br /&gt;
// The brand colour setting description.                                                                                            &lt;br /&gt;
$string[&#039;brandcolor_desc&#039;] = &#039;The accent colour.&#039;;     &lt;br /&gt;
// A description shown in the admin theme selector.                                                                                 &lt;br /&gt;
$string[&#039;choosereadme&#039;] = &#039;Theme photo is a child theme of Boost. It adds the ability to upload background photos.&#039;;                &lt;br /&gt;
// Name of the settings pages.                                                                                                      &lt;br /&gt;
$string[&#039;configtitle&#039;] = &#039;Photo settings&#039;;                                                                                          &lt;br /&gt;
// Name of the first settings tab.                                                                                                  &lt;br /&gt;
$string[&#039;generalsettings&#039;] = &#039;General settings&#039;;                                                                                    &lt;br /&gt;
// The name of our plugin.                                                                                                          &lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Photo&#039;;                                                                                                    &lt;br /&gt;
// Preset files setting.                                                                                                            &lt;br /&gt;
$string[&#039;presetfiles&#039;] = &#039;Additional theme preset files&#039;;                                                                           &lt;br /&gt;
// Preset files help text.                                                                                                          &lt;br /&gt;
$string[&#039;presetfiles_desc&#039;] = &#039;Preset files can be used to dramatically alter the appearance of the theme. See &amp;lt;a href=https://docs.moodle.org/dev/Boost_Presets&amp;gt;Boost presets&amp;lt;/a&amp;gt; for information on creating and sharing your own preset files, and see the &amp;lt;a href=http://moodle.net/boost&amp;gt;Presets repository&amp;lt;/a&amp;gt; for presets that others have shared.&#039;;&lt;br /&gt;
// Preset setting.                                                                                                                  &lt;br /&gt;
$string[&#039;preset&#039;] = &#039;Theme preset&#039;;                                                                                                 &lt;br /&gt;
// Preset help text.                                                                                                                &lt;br /&gt;
$string[&#039;preset_desc&#039;] = &#039;Pick a preset to broadly change the look of the theme.&#039;;                                                  &lt;br /&gt;
// Raw SCSS setting.                                                                                                                &lt;br /&gt;
$string[&#039;rawscss&#039;] = &#039;Raw SCSS&#039;;                                                                                                    &lt;br /&gt;
// Raw SCSS setting help text.                                                                                                      &lt;br /&gt;
$string[&#039;rawscss_desc&#039;] = &#039;Use this field to provide SCSS or CSS code which will be injected at the end of the style sheet.&#039;;       &lt;br /&gt;
// Raw initial SCSS setting.                                                                                                        &lt;br /&gt;
$string[&#039;rawscsspre&#039;] = &#039;Raw initial SCSS&#039;;                                                                                         &lt;br /&gt;
// Raw initial SCSS setting help text.                                                                                              &lt;br /&gt;
$string[&#039;rawscsspre_desc&#039;] = &#039;In this field you can provide initialising SCSS code, it will be injected before everything else. Most of the time you will use this setting to define variables.&#039;;&lt;br /&gt;
// We need to include a lang string for each block region.                                                                          &lt;br /&gt;
$string[&#039;region-side-pre&#039;] = &#039;Right&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We aren&#039;t quite there yet as you will notice if you try and upload a preset file and then choose it. The &amp;quot;theme_boost_get_main_scss_content&amp;quot; function from Boost is expecting the preset files to be stored in a file area for theme_boost only. We need to add this function to our own theme and tweak it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is the function that returns the SCSS source for the main file in our theme. We override the boost version because          &lt;br /&gt;
// we want to allow presets uploaded to our own theme file area to be selected in the preset list.                                  &lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {                                                                                                   &lt;br /&gt;
    return theme_photo_get_main_scss_content($theme);                                                                               &lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        // This preset file was fetched from the file area for theme_photo and not theme_boost (see the line above).                &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}             &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Stop and try it out ===&lt;br /&gt;
So now what is working and what isn&#039;t. Well - everything should be working and you should have a nice new theme extending boost with it&#039;s own settings pages. When Boost gets updates for bug fixes your new theme will inherit those fixes as it inherits all the SCSS and templates from theme boost. In addition your new theme will accept preset files and supports all the same features and settings as boost, ready to add more.&lt;br /&gt;
&lt;br /&gt;
== Take it further ==&lt;br /&gt;
Now we have our very nice starting point we can start changing or adding features, customising templates and output or tweaking the SCSS.&lt;br /&gt;
&lt;br /&gt;
=== Add some new settings ===&lt;br /&gt;
&lt;br /&gt;
From this point in the tutorial we will start adding features to our theme to extend it and make it AWESOME!&lt;br /&gt;
&lt;br /&gt;
Lets start with a new setting to set a background image on the login page. As you saw earlier, our theme defines it&#039;s list of settings in a file called settings.php. See [[Admin settings]] for more information about adding admin settings to any plugin. All of the different kinds of admin settings can be found in lib/adminlib.php. In our case we will want to add a setting which allows an admin to upload an image file. This is an &amp;quot;admin_setting_configstoredfile&amp;quot; and we add it to our theme by adding this code to the settings.php file inside and at the end of the &amp;quot;if ($ADMIN-&amp;gt;fulltree) {&amp;quot; condition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    // Login page background setting.                                                                                               &lt;br /&gt;
    // We use variables for readability.                                                                                            &lt;br /&gt;
    $name = &#039;theme_photo/loginbackgroundimage&#039;;                                                                                     &lt;br /&gt;
    $title = get_string(&#039;loginbackgroundimage&#039;, &#039;theme_photo&#039;);                                                                     &lt;br /&gt;
    $description = get_string(&#039;loginbackgroundimage_desc&#039;, &#039;theme_photo&#039;);                                                          &lt;br /&gt;
    // This creates the new setting.                                                                                                &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;loginbackgroundimage&#039;);                             &lt;br /&gt;
    // This means that theme caches will automatically be cleared when this setting is changed.                                     &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    // We always have to add the setting to a page for it to have any effect.                                                       &lt;br /&gt;
    $page-&amp;gt;add($setting);       &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need to add new lang strings to our language file.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lang/en/theme_photo.php&amp;quot;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Background image for login page.                                                                                                 &lt;br /&gt;
$string[&#039;loginbackgroundimage&#039;] = &#039;Login page background image&#039;;                                                                    &lt;br /&gt;
// Background image for login page.                                                                                                 &lt;br /&gt;
$string[&#039;loginbackgroundimage_desc&#039;] = &#039;An image that will be stretched to fill the background of the login page.&#039;;                 &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have a new setting that lets us upload a file - but it doesn&#039;t actually do anything yet. We need to update the theme to set this image background on the login page.&lt;br /&gt;
&lt;br /&gt;
In order to change the SCSS for our theme we will add 2 additional SCSS files and include them before and after our main scss.&lt;br /&gt;
&lt;br /&gt;
We already have a function in our lib.php file which fetches the main SCSS for our theme. This is a good point to include additional SCSS files. We can add 2 lines to the end of this function to achieve this.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        // This preset file was fetched from the file area for theme_photo and not theme_boost (see the line above).                &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Pre CSS - this is loaded AFTER any prescss from the setting but before the main scss.                                        &lt;br /&gt;
    $pre = file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/photo/scss/pre.scss&#039;);                                                         &lt;br /&gt;
    // Post CSS - this is loaded AFTER the main scss but before the extra scss from the setting.                                    &lt;br /&gt;
    $post = file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/photo/scss/post.scss&#039;);                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Combine them together.                                                                                                       &lt;br /&gt;
    return $pre . &amp;quot;\n&amp;quot; . $scss . &amp;quot;\n&amp;quot; . $post;                                                                                      &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;scss/pre.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
// Pre SCSS for the theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;scss/post.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
// Post SCSS for the theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Why do we use pre and post SCSS? ====&lt;br /&gt;
SCSS/SASS is a powerful language for creating CSS. It supports variables, functions, loops just like php. For lots of information and an introduction to SCSS read about [https://en.wikipedia.org/wiki/Sass_(stylesheet_language) Sass on wikipedia]. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pre SCSS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In Boost we use many variables when creating style rules.&lt;br /&gt;
&lt;br /&gt;
When declaring a variable in SCSS - it is best practice to define it like this:&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
$mycoolcolour: #FF0 !default;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this means is - if this variable is not defined already - set it to the hex value &#039;#FF0&#039;;&lt;br /&gt;
&lt;br /&gt;
So by setting this variable in some PRE scss we can override the default value of this variable everywhere it is used. Boost is built with the [https://v4-alpha.getbootstrap.com/ Bootstrap 4 (Alpha 4)] CSS Framework. This is a framework which uses SCSS to provide many extremely useful layouts and components which can be reused without adding specific CSS rules to style every page. Because bootstrap consistently uses variables we can customise many of these components easily by setting the value of the variables before we include the Bootstrap SCSS files.&lt;br /&gt;
&lt;br /&gt;
Many variables are available in /theme/boost/scss/bootstrap/_variables.scss - as an example we can change the look of all buttons and input fields with this one variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
$border-radius: 8px;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Post SCSS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Post SCSS is useful for defining full CSS rules. Because they are included last, they override any previous matching selector with the same [https://en.wikipedia.org/wiki/Cascading_Style_Sheets#Specificity Specificity].&lt;br /&gt;
&lt;br /&gt;
=== Tips for customising Moodle with SCSS (or CSS) ===&lt;br /&gt;
Some handy things to know when you are new to theming is that Moodle adds some classes to every page that helps you target a specific page or set of pages with some style rules. &lt;br /&gt;
&lt;br /&gt;
If you inspect a moodle page and look at the body tag you will see a long list of classes e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code html&amp;gt;&lt;br /&gt;
&amp;lt;body id=&amp;quot;page-course-view-weeks&amp;quot; class=&amp;quot;format-weeks  path-course path-course-view safari dir-ltr lang-en yui-skin-sam yui3-skin-sam damyon-per-in-moodle-com--stable_master pagelayout-course course-11 context-497 category-1 drawer-open-left jsenabled&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can see from this example that each page gets an id. This is a simplified representation of the current page in the navigation. In this example we are looking at the course page and this course is using the weeks format. &lt;br /&gt;
&lt;br /&gt;
The classes on the body tag can also be used to target a page or set of pages.&lt;br /&gt;
* &amp;lt;code&amp;gt;format-weeks&amp;lt;/code&amp;gt; The course format&lt;br /&gt;
* &amp;lt;code&amp;gt;path-course path-course-view&amp;lt;/code&amp;gt; The parts of the bread-crumb leading up to the current page (The current page is what goes in the id)&lt;br /&gt;
* &amp;lt;code&amp;gt;safari&amp;lt;/code&amp;gt; Some server side guessing of the browser type - it&#039;s not accurate so I would not rely on it&lt;br /&gt;
* &amp;lt;code&amp;gt;dir-ltr&amp;lt;/code&amp;gt; The direction of the current language for the page ( dir-rtl for RTL languages )&lt;br /&gt;
* &amp;lt;code&amp;gt;lang-en&amp;lt;/code&amp;gt; The current language of the page&lt;br /&gt;
* &amp;lt;code&amp;gt;yui*&amp;lt;/code&amp;gt; Legacy yui classes - ignore these&lt;br /&gt;
* &amp;lt;code&amp;gt;damyon-per-in-moodle-com--stable_master&amp;lt;/code&amp;gt; The current hostname for the site + the site name&lt;br /&gt;
* &amp;lt;code&amp;gt;pagelayout-course&amp;lt;/code&amp;gt; The layout type for the current page&lt;br /&gt;
* &amp;lt;code&amp;gt;course-11&amp;lt;/code&amp;gt; The id of the current course&lt;br /&gt;
* &amp;lt;code&amp;gt;context-497&amp;lt;/code&amp;gt; The current context id&lt;br /&gt;
* &amp;lt;code&amp;gt;category-1&amp;lt;/code&amp;gt; The category for the current course&lt;br /&gt;
* &amp;lt;code&amp;gt;drawer-open-left&amp;lt;/code&amp;gt; Added / removed when the navigation drawer is opened / closed in Boost&lt;br /&gt;
* &amp;lt;code&amp;gt;jsenabled&amp;lt;/code&amp;gt; True if the browser supports javascript&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/dev/Themes_overview#.3Cbody.3E_CSS_id_and_classes Read about Body id and classes].&lt;br /&gt;
&lt;br /&gt;
In our example the page layout is the most useful here as we have a specific page layout for login pages. We can now craft a rule that applies a background image only to login pages using &amp;quot;body.pagelayout-login&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How do we refer to an image in SCSS ? ===&lt;br /&gt;
So now we can add a rule to the post.scss which will set the background image for the login page. First we need to know how to construct a url to the background images from our stylesheet. &lt;br /&gt;
&lt;br /&gt;
In stylesheets in Moodle we can use a special pix tag to refer to images from our theme. The rule to attach the background image looks like this:&lt;br /&gt;
&#039;&#039;scss/post.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
body.pagelayout-login {                                                                                                             &lt;br /&gt;
    background-image: url([[pix:theme_photo|loginbackgroundimage]]);                                                                &lt;br /&gt;
    background-size: cover;                                                                                                         &lt;br /&gt;
}                          &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are 2 important parts to this tag (the bit in square brackets). The first is &amp;quot;theme_photo&amp;quot;. In this case we are passing a component name, the image serving code in theme_config::resolve_image_location() will then look for an image file in several locations. One of these is in &amp;quot;$CFG-&amp;gt;dataroot/pix_plugins/$type/$plugin/$image&amp;quot;. We can use this to make sure the image gets served correctly by copying the file saved in the setting to this location every time it is updated. (There is an alterative way we could do this by implementing pluginfile.php in our theme - which you can read about in the [[File API]] ).&lt;br /&gt;
&lt;br /&gt;
If we had just passed the value &amp;quot;theme&amp;quot; the image serving code would have looked for the image in the &amp;quot;pix&amp;quot; folder of our theme.&lt;br /&gt;
&lt;br /&gt;
So - we need this final change to copy the image file into our dataroot each time the setting is changed.&lt;br /&gt;
&lt;br /&gt;
In the settings file we will update the callback to a new function which we will define in our lib.php.&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Login page background setting.                                                                                               &lt;br /&gt;
    // We use variables for readability.                                                                                            &lt;br /&gt;
    $name = &#039;theme_photo/loginbackgroundimage&#039;;                                                                                     &lt;br /&gt;
    $title = get_string(&#039;loginbackgroundimage&#039;, &#039;theme_photo&#039;);                                                                     &lt;br /&gt;
    $description = get_string(&#039;loginbackgroundimage_desc&#039;, &#039;theme_photo&#039;);                                                          &lt;br /&gt;
    // This creates the new setting.                                                                                                &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;loginbackgroundimage&#039;);                             &lt;br /&gt;
    // This function will copy the image into the data_root location it can be served from.                                         &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_photo_update_settings_images&#039;);                                                            &lt;br /&gt;
    // We always have to add the setting to a page for it to have any effect.                                                       &lt;br /&gt;
    $page-&amp;gt;add($setting);&lt;br /&gt;
    //This will commit the background image setting. If you do not add this line the Login page background setting will not be shown.&lt;br /&gt;
    $settings-&amp;gt;add($page);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_update_settings_images($settingname) {                                                                         &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // The setting name that was updated comes as a string like &#039;s_theme_photo_loginbackgroundimage&#039;.                               &lt;br /&gt;
    // We split it on &#039;_&#039; characters.                                                                                               &lt;br /&gt;
    $parts = explode(&#039;_&#039;, $settingname);                                                                                            &lt;br /&gt;
    // And get the last one to get the setting name..                                                                               &lt;br /&gt;
    $settingname = end($parts);                                                                                                     &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Admin settings are stored in system context.                                                                                 &lt;br /&gt;
    $syscontext = context_system::instance();                                                                                       &lt;br /&gt;
    // This is the component name the setting is stored in.                                                                         &lt;br /&gt;
    $component = &#039;theme_photo&#039;;                                                                                                     &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // This is the value of the admin setting which is the filename of the uploaded file.                                           &lt;br /&gt;
    $filename = get_config($component, $settingname);                                                                               &lt;br /&gt;
    // We extract the file extension because we want to preserve it.                                                                &lt;br /&gt;
    $extension = substr($filename, strrpos($filename, &#039;.&#039;) + 1);                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // This is the path in the moodle internal file system.                                                                         &lt;br /&gt;
    $fullpath = &amp;quot;/{$syscontext-&amp;gt;id}/{$component}/{$settingname}/0{$filename}&amp;quot;;                                                      &lt;br /&gt;
    // Get an instance of the moodle file storage.                                                                                  &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
    // This is an efficient way to get a file if we know the exact path.                                                            &lt;br /&gt;
    if ($file = $fs-&amp;gt;get_file_by_hash(sha1($fullpath))) {                                                                           &lt;br /&gt;
        // We got the stored file - copy it to dataroot.                                                                            &lt;br /&gt;
        // This location matches the searched for location in theme_config::resolve_image_location.                                 &lt;br /&gt;
        $pathname = $CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039; . $settingname . &#039;.&#039; . $extension;                                 &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // This pattern matches any previous files with maybe different file extensions.                                            &lt;br /&gt;
        $pathpattern = $CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039; . $settingname . &#039;.*&#039;;                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Make sure this dir exists.                                                                                               &lt;br /&gt;
        @mkdir($CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039;, $CFG-&amp;gt;directorypermissions, true);                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Delete any existing files for this setting.                                                                              &lt;br /&gt;
        foreach (glob($pathpattern) as $filename) {                                                                                 &lt;br /&gt;
            @unlink($filename);                                                                                                     &lt;br /&gt;
        }                                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Copy the current file to this location.                                                                                  &lt;br /&gt;
        $file-&amp;gt;copy_content_to($pathname);                                                                                          &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Reset theme caches.                                                                                                          &lt;br /&gt;
    theme_reset_all_caches();                                                                                                       &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To edit the setting go to &#039;&#039;&#039;Site Administration &amp;gt; Appearance &amp;gt; Photo &amp;gt; Advanced setting&#039;&#039;&#039;. You will now see the Login page background setting.&lt;br /&gt;
It is now easy to add a new background image setting for every layout type. I can re-use this theme_photo_update_settings_images callback for each one - so all I have to do is add the setting to the settings.php file, add the SCSS rule to the scss/post.scss file and add the lang strings to the language file.&lt;br /&gt;
&lt;br /&gt;
Thats it for this tutorial, but there are [[:Category:Themes| more Themes docs]] to browse.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Themes]]&lt;/div&gt;</summary>
		<author><name>Meeth</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Creating_a_theme_based_on_boost&amp;diff=57737</id>
		<title>Creating a theme based on boost</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Creating_a_theme_based_on_boost&amp;diff=57737"/>
		<updated>2020-07-30T11:09:17Z</updated>

		<summary type="html">&lt;p&gt;Meeth: /* Duplicate the settings from Boost */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 3.2}}&lt;br /&gt;
{{Template:Themes}}&lt;br /&gt;
&lt;br /&gt;
This is a tutorial for how to create a new theme in any version of Moodle from 3.2 and later.&lt;br /&gt;
&lt;br /&gt;
Moodle 3.2 introduced a new core theme named &amp;quot;Boost&amp;quot; which is a great starting point for themers wanting to build a modern Moodle theme utilising all the latest features available to themes in Moodle.  If you aren&#039;t sure where to start, then START HERE!  :-)&lt;br /&gt;
&lt;br /&gt;
== Getting started ==&lt;br /&gt;
What is a theme? A theme in Moodle is just another type of plugin that can be developed. Themes are responsible for setting up the structure of each page and have the ability to customise the output of any page in Moodle.&lt;br /&gt;
&lt;br /&gt;
This tutorial is based on a working theme named &amp;quot;theme_photo&amp;quot; you can download it or view the source code for it here: https://github.com/damyon/moodle-theme_photo&lt;br /&gt;
&lt;br /&gt;
=== Choosing a name ===&lt;br /&gt;
Your new theme will need a name. Try and think of something short and memorable - and make sure it is not a name that has already been used by someone else. A quick search on the moodle.org/plugins can save you a lot of work renaming things later.&lt;br /&gt;
&lt;br /&gt;
Lets call our new example theme &amp;quot;photo&amp;quot; as we will add some settings to allow &amp;quot;photos&amp;quot; in various places in Moodle.&lt;br /&gt;
&lt;br /&gt;
=== Starting files ===&lt;br /&gt;
As a plugin, themes must start with the basic structure of a plugin in Moodle. See https://docs.moodle.org/dev/Tutorial#The_skeleton_of_your_plugin for an overview of the files common to all plugins in Moodle.&lt;br /&gt;
&lt;br /&gt;
Following this guide we can start creating our theme. First we create the folder for the new theme under &amp;quot;/theme/&amp;quot; folder in the Moodle root directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
/theme/photo/&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we need to add some standard plugin files to our theme. First is version.php&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/theme/photo/version.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the version of the plugin.                                                                                               &lt;br /&gt;
$plugin-&amp;gt;version = &#039;2016102100&#039;;                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the version of Moodle this plugin requires.                                                                              &lt;br /&gt;
$plugin-&amp;gt;requires = &#039;2016070700&#039;;                                                                                                   &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the component name of the plugin - it always starts with &#039;theme_&#039;                                                        &lt;br /&gt;
// for themes and should be the same as the name of the folder.                                                                     &lt;br /&gt;
$plugin-&amp;gt;component = &#039;theme_photo&#039;;                                                                                                 &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a list of plugins, this plugin depends on (and their versions).                                                          &lt;br /&gt;
$plugin-&amp;gt;dependencies = [                                                                                                           &lt;br /&gt;
    &#039;theme_boost&#039; =&amp;gt; &#039;2016102100&#039;                                                                                                   &lt;br /&gt;
];                                                                              &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need a language file so that all our strings can be translated into different languages. The name of this file is the component name of our plugin and it sits in the lang/en/ folder for our plugin. We can include translations of our plugin, but we can also provide translations via the https://lang.moodle.org/ website once our plugin has been published to the plugins database at http://www.moodle.org/plugins/.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/theme/photo/lang/en/theme_photo.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// A description shown in the admin theme selector.                                                                                 &lt;br /&gt;
$string[&#039;choosereadme&#039;] = &#039;Theme photo is a child theme of Boost. It adds the ability to upload background photos.&#039;;                &lt;br /&gt;
// The name of our plugin.                                                                                                          &lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Photo&#039;;                                                                                                    &lt;br /&gt;
// We need to include a lang string for each block region.                                                                          &lt;br /&gt;
$string[&#039;region-side-pre&#039;] = &#039;Right&#039;;                                         &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Theme specific files ===&lt;br /&gt;
Theme plugins have a few more standard files they need to define. &lt;br /&gt;
&lt;br /&gt;
Themes require a favicon file to show in the address bar. See [[http://docs.moodle.org/en/Favicon Favicon]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;pix/favicon.ico&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(Image file not shown).&lt;br /&gt;
&lt;br /&gt;
Themes also require an example screenshot to be displayed in the theme selector.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;pix/screenshot.jpg&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(Image file not shown).&lt;br /&gt;
&lt;br /&gt;
Themes require a lib.php file. This file contains callbacks used by various API&#039;s in Moodle. Initially this file can be empty, but as we add features to our theme we will need to add some functions here.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
// We will add callbacks here as we add features to our theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Theme config goes in a config.php file. This is one of the most important files in our theme. Once we add this file we will be ready to test our theme for the first time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
// $THEME is defined before this page is included and we can define settings by adding properties to this global object.            &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// The first setting we need is the name of the theme. This should be the last part of the component name, and the same             &lt;br /&gt;
// as the directory name for our theme.                                                                                             &lt;br /&gt;
$THEME-&amp;gt;name = &#039;photo&#039;;                                                                                                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This setting list the style sheets we want to include in our theme. Because we want to use SCSS instead of CSS - we won&#039;t        &lt;br /&gt;
// list any style sheets. If we did we would list the name of a file in the /style/ folder for our theme without any css file      &lt;br /&gt;
// extensions.                                                                                                                      &lt;br /&gt;
$THEME-&amp;gt;sheets = [];                                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a setting that can be used to provide some styling to the content in the TinyMCE text editor. This is no longer the      &lt;br /&gt;
// default text editor and &amp;quot;Atto&amp;quot; does not need this setting so we won&#039;t provide anything. If we did it would work the same         &lt;br /&gt;
// as the previous setting - listing a file in the /styles/ folder.                                                                 &lt;br /&gt;
$THEME-&amp;gt;editor_sheets = [];                                                                                                         &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a critical setting. We want to inherit from theme_boost because it provides a great starting point for SCSS bootstrap4   &lt;br /&gt;
// themes. We could add more than one parent here to inherit from multiple parents, and if we did they would be processed in        &lt;br /&gt;
// order of importance (later themes overriding earlier ones). Things we will inherit from the parent theme include                 &lt;br /&gt;
// styles and mustache templates and some (not all) settings.                                                                       &lt;br /&gt;
$THEME-&amp;gt;parents = [&#039;boost&#039;];                                                                                                        &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// A dock is a way to take blocks out of the page and put them in a persistent floating area on the side of the page. Boost         &lt;br /&gt;
// does not support a dock so we won&#039;t either - but look at bootstrapbase for an example of a theme with a dock.                    &lt;br /&gt;
$THEME-&amp;gt;enable_dock = false;                                                                                                        &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is an old setting used to load specific CSS for some YUI JS. We don&#039;t need it in Boost based themes because Boost           &lt;br /&gt;
// provides default styling for the YUI modules that we use. It is not recommended to use this setting anymore.                     &lt;br /&gt;
$THEME-&amp;gt;yuicssmodules = array();                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// Most themes will use this rendererfactory as this is the one that allows the theme to override any other renderer.               &lt;br /&gt;
$THEME-&amp;gt;rendererfactory = &#039;theme_overridden_renderer_factory&#039;;                                                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a list of blocks that are required to exist on all pages for this theme to function correctly. For example               &lt;br /&gt;
// bootstrap base requires the settings and navigation blocks because otherwise there would be no way to navigate to all the        &lt;br /&gt;
// pages in Moodle. Boost does not require these blocks because it provides other ways to navigate built into the theme.            &lt;br /&gt;
$THEME-&amp;gt;requiredblocks = &#039;&#039;;   &lt;br /&gt;
&lt;br /&gt;
// This is a feature that tells the blocks library not to use the &amp;quot;Add a block&amp;quot; block. We don&#039;t want this in boost based themes because&lt;br /&gt;
// it forces a block region into the page when editing is enabled and it takes up too much room.&lt;br /&gt;
$THEME-&amp;gt;addblockposition = BLOCK_ADDBLOCK_POSITION_FLATNAV;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ready set go! ===&lt;br /&gt;
If you have been following along - now we are at the point where we can actually install and test our new theme. Try it now by visiting the admin notifications page to install the new plugin, and then choosing the new theme from the theme selector.&lt;br /&gt;
&lt;br /&gt;
[[https://docs.moodle.org/en/Standard_themes#Theme_selector Theme selector]]&lt;br /&gt;
&lt;br /&gt;
When you choose the new theme - you will find that it looks exactly the same as Boost. At this point with our minimal configuration - we are inheriting almost everything from our parent theme including styles and templates. You will notice though that we don&#039;t inherit the settings from our parent theme. If you choose a different preset in Boost - it is not applied in this child theme.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&lt;br /&gt;
Note: make sure your config.php file contains $THEME-&amp;gt;hidefromselector = false; (or at least set to false) or else, your theme wont show up in theme selector.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What if I want the settings too? ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&lt;br /&gt;
This section is included for completeness - but it is not recommended for themes to utilise settings from their parents. To find out how to duplicate the settings from the parent theme so they operate independently skip to [[#Duplicate the settings from Boost]].&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If I want the settings from Boost to apply to my child theme as well I need to know a bit about how each of the settings in Boost is applied to make them work in my child theme.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Setting 1 - preset.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;preset&amp;quot; file is the file that is used as the main file for scss compilation. In Boost this is controlled by the theme config value:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {&lt;br /&gt;
    return theme_boost_get_main_scss_content($theme);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_boost&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this function is doing is checking for a theme setting &amp;quot;preset&amp;quot; and either fetching the file from Moodles internal file storage, or from the /preset/ folder. The function then returns the contents of this file.&lt;br /&gt;
&lt;br /&gt;
It does not automatically work for our child theme because we have no setting named &amp;quot;preset&amp;quot; in our child theme and this code is not searching the theme parents for the setting. If we wanted it to apply we could do this in our child theme:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This setting defines the main scss file for our theme to be compiled. We could set it to a static file in the scss folder or to a function which returns the SCSS based on theme settings.&lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {&lt;br /&gt;
&lt;br /&gt;
    // We need to load the config for our parent theme because that is where the preset setting is defined.&lt;br /&gt;
    $parentconfig = theme_config::load(&#039;boost&#039;);&lt;br /&gt;
    // Call a function from our parent themes lib.php file to fetch the content of the themes main SCSS file based on it&#039;s own config, not ours.&lt;br /&gt;
    return theme_boost_get_main_scss_content($parentconfig);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings 2+3 brandcolor + scsspre&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The way these settings work is they generate a chunk of SCSS to be prepended to the main scss file. In boost they work like this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;prescsscallback = &#039;theme_boost_get_pre_scss&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_pre_scss($theme) {                                                                                         &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $configurable = [                                                                                                               &lt;br /&gt;
        // Config key =&amp;gt; [variableName, ...].                                                                                       &lt;br /&gt;
        &#039;brandcolor&#039; =&amp;gt; [&#039;brand-primary&#039;],                                                                                          &lt;br /&gt;
    ];                                                                                                                              &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Prepend variables first.                                                                                                     &lt;br /&gt;
    foreach ($configurable as $configkey =&amp;gt; $targets) {                                                                             &lt;br /&gt;
        $value = isset($theme-&amp;gt;settings-&amp;gt;{$configkey}) ? $theme-&amp;gt;settings-&amp;gt;{$configkey} : null;                                     &lt;br /&gt;
        if (empty($value)) {                                                                                                        &lt;br /&gt;
            continue;                                                                                                               &lt;br /&gt;
        }                                                                                                                           &lt;br /&gt;
        array_map(function($target) use (&amp;amp;$scss, $value) {                                                                          &lt;br /&gt;
            $scss .= &#039;$&#039; . $target . &#039;: &#039; . $value . &amp;quot;;\n&amp;quot;;                                                                         &lt;br /&gt;
        }, (array) $targets);                                                                                                       &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Prepend pre-scss.                                                                                                            &lt;br /&gt;
    if (!empty($theme-&amp;gt;settings-&amp;gt;scsspre)) {                                                                                        &lt;br /&gt;
        $scss .= $theme-&amp;gt;settings-&amp;gt;scsspre;                                                                                         &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}  &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this code is doing is: &lt;br /&gt;
* looping over a list of theme settings that map to a SCSS variable and building some SCSS to initialise that variable from the setting. In Boost there is only one * brandprimary - but if we wanted to expose more bootstrap variables as theme settings we could use this function as a template in our child theme and add more settings to the $configurable array.&lt;br /&gt;
* Adding all of the raw SCSS from the scsspre theme setting&lt;br /&gt;
* Returning the whole thing as a string to be added before the main scss file.&lt;br /&gt;
&lt;br /&gt;
If we want this code to work in our child theme, using the settings from Boost we could do this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is a function that returns some SCSS as a string to prepend to the main SCSS file.                                          &lt;br /&gt;
$THEME-&amp;gt;prescsscallback = &#039;theme_photo_get_pre_scss&#039;;               &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Function to return the SCSS to prepend to our main SCSS for this theme.&lt;br /&gt;
// Note the function name starts with the component name because this is a global function and we don&#039;t want namespace clashes.&lt;br /&gt;
function theme_photo_get_pre_scss($theme) {&lt;br /&gt;
    // Load the settings from the parent.                                                                                           &lt;br /&gt;
    $theme = theme_config::load(&#039;boost&#039;);                                                                                           &lt;br /&gt;
    // Call the parent themes get_pre_scss function.                                                                                &lt;br /&gt;
    return theme_boost_get_pre_scss($theme);                         &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Setting 4 scss (post)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The final setting from Boost is a raw text field which adds SCSS to the end of the main SCSS file. This is a useful place to add style rules as they will override previously defined styles with the same specificity. It is applied in Boost by the following lines:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;extrascsscallback = &#039;theme_boost_get_extra_scss&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_extra_scss($theme) {                                                                                       &lt;br /&gt;
    return !empty($theme-&amp;gt;settings-&amp;gt;scss) ? $theme-&amp;gt;settings-&amp;gt;scss : &#039;&#039;;                                                            &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is just returning the value of the setting as a string.&lt;br /&gt;
&lt;br /&gt;
To make this setting apply in our child theme too - we use similar code to the previous sections.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is a function that returns some SCSS as a string to append to the main SCSS file.                                          &lt;br /&gt;
$THEME-&amp;gt;extrascsscallback = &#039;theme_photo_get_extra_scss&#039;;               &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Function to return the SCSS to append to our main SCSS for this theme.&lt;br /&gt;
// Note the function name starts with the component name because this is a global function and we don&#039;t want namespace clashes.&lt;br /&gt;
function theme_photo_get_extra_scss($theme) {&lt;br /&gt;
    // Load the settings from the parent.                                                                                           &lt;br /&gt;
    $theme = theme_config::load(&#039;boost&#039;);                                                                                           &lt;br /&gt;
    // Call the parent themes get_extra_scss function.                                                                                &lt;br /&gt;
    return theme_boost_get_extra_scss($theme);                         &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Duplicate the settings from Boost  ===&lt;br /&gt;
&lt;br /&gt;
This is the recommended way to extend boost as your child theme will not be affected by changes to the Boost settings, and both themes can be in use with different settings applied.&lt;br /&gt;
&lt;br /&gt;
All that needs to happen is to create theme settings in the child theme that match each of the settings in the parent theme. You will need to add matching language strings for each of these settings in the language file.&lt;br /&gt;
&lt;br /&gt;
This example shows how to do it - We are re-using the nice looking theme_boost_admin_settingspage_tabs class from boost and creating duplicate versions of each of the settings.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is used for performance, we don&#039;t need to know about these settings on every page in Moodle, only when                      &lt;br /&gt;
// we are looking at the admin settings pages.                                                                                      &lt;br /&gt;
if ($ADMIN-&amp;gt;fulltree) {                                                                                                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Boost provides a nice setting page which splits settings onto separate tabs. We want to use it here.                         &lt;br /&gt;
    $settings = new theme_boost_admin_settingspage_tabs(&#039;themesettingphoto&#039;, get_string(&#039;configtitle&#039;, &#039;theme_photo&#039;));             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Each page is a tab - the first is the &amp;quot;General&amp;quot; tab.                                                                         &lt;br /&gt;
    $page = new admin_settingpage(&#039;theme_photo_general&#039;, get_string(&#039;generalsettings&#039;, &#039;theme_photo&#039;));                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Replicate the preset setting from boost.                                                                                     &lt;br /&gt;
    $name = &#039;theme_photo/preset&#039;;                                                                                                   &lt;br /&gt;
    $title = get_string(&#039;preset&#039;, &#039;theme_photo&#039;);                                                                                   &lt;br /&gt;
    $description = get_string(&#039;preset_desc&#039;, &#039;theme_photo&#039;);                                                                        &lt;br /&gt;
    $default = &#039;default.scss&#039;;                                                                                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // We list files in our own file area to add to the drop down. We will provide our own function to                              &lt;br /&gt;
    // load all the presets from the correct paths.                                                                                 &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
    $files = $fs-&amp;gt;get_area_files($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;itemid, filepath, filename&#039;, false);                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $choices = [];                                                                                                                  &lt;br /&gt;
    foreach ($files as $file) {                                                                                                     &lt;br /&gt;
        $choices[$file-&amp;gt;get_filename()] = $file-&amp;gt;get_filename();                                                                    &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
    // These are the built in presets from Boost.                                                                                   &lt;br /&gt;
    $choices[&#039;default.scss&#039;] = &#039;default.scss&#039;;                                                                                      &lt;br /&gt;
    $choices[&#039;plain.scss&#039;] = &#039;plain.scss&#039;;                                                                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $setting = new admin_setting_configselect($name, $title, $description, $default, $choices);                                     &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Preset files setting.                                                                                                        &lt;br /&gt;
    $name = &#039;theme_photo/presetfiles&#039;;                                                                                              &lt;br /&gt;
    $title = get_string(&#039;presetfiles&#039;,&#039;theme_photo&#039;);                                                                               &lt;br /&gt;
    $description = get_string(&#039;presetfiles_desc&#039;, &#039;theme_photo&#039;);                                                                   &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;preset&#039;, 0,                                         &lt;br /&gt;
        array(&#039;maxfiles&#039; =&amp;gt; 20, &#039;accepted_types&#039; =&amp;gt; array(&#039;.scss&#039;)));                                                               &lt;br /&gt;
    $page-&amp;gt;add($setting);     &lt;br /&gt;
&lt;br /&gt;
    // Variable $brand-color.                                                                                                       &lt;br /&gt;
    // We use an empty default value because the default colour should come from the preset.                                        &lt;br /&gt;
    $name = &#039;theme_photo/brandcolor&#039;;                                                                                               &lt;br /&gt;
    $title = get_string(&#039;brandcolor&#039;, &#039;theme_photo&#039;);                                                                               &lt;br /&gt;
    $description = get_string(&#039;brandcolor_desc&#039;, &#039;theme_photo&#039;);                                                                    &lt;br /&gt;
    $setting = new admin_setting_configcolourpicker($name, $title, $description, &#039;&#039;);                                               &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Must add the page after definiting all the settings!                                                                         &lt;br /&gt;
    $settings-&amp;gt;add($page);                                                                                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Advanced settings.                                                                                                           &lt;br /&gt;
    $page = new admin_settingpage(&#039;theme_photo_advanced&#039;, get_string(&#039;advancedsettings&#039;, &#039;theme_photo&#039;));                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Raw SCSS to include before the content.                                                                                      &lt;br /&gt;
    $setting = new admin_setting_configtextarea(&#039;theme_photo/scsspre&#039;,                                                              &lt;br /&gt;
        get_string(&#039;rawscsspre&#039;, &#039;theme_photo&#039;), get_string(&#039;rawscsspre_desc&#039;, &#039;theme_photo&#039;), &#039;&#039;, PARAM_RAW);                      &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Raw SCSS to include after the content.                                                                                       &lt;br /&gt;
    $setting = new admin_setting_configtextarea(&#039;theme_photo/scss&#039;, get_string(&#039;rawscss&#039;, &#039;theme_photo&#039;),                           &lt;br /&gt;
        get_string(&#039;rawscss_desc&#039;, &#039;theme_photo&#039;), &#039;&#039;, PARAM_RAW);                                                                  &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                             &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lang/en/theme_photo.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
// The name of the second tab in the theme settings.                                                                                &lt;br /&gt;
$string[&#039;advancedsettings&#039;] = &#039;Advanced settings&#039;;                                                                                  &lt;br /&gt;
// The brand colour setting.                                                                                                        &lt;br /&gt;
$string[&#039;brandcolor&#039;] = &#039;Brand colour&#039;;                                                                                             &lt;br /&gt;
// The brand colour setting description.                                                                                            &lt;br /&gt;
$string[&#039;brandcolor_desc&#039;] = &#039;The accent colour.&#039;;     &lt;br /&gt;
// A description shown in the admin theme selector.                                                                                 &lt;br /&gt;
$string[&#039;choosereadme&#039;] = &#039;Theme photo is a child theme of Boost. It adds the ability to upload background photos.&#039;;                &lt;br /&gt;
// Name of the settings pages.                                                                                                      &lt;br /&gt;
$string[&#039;configtitle&#039;] = &#039;Photo settings&#039;;                                                                                          &lt;br /&gt;
// Name of the first settings tab.                                                                                                  &lt;br /&gt;
$string[&#039;generalsettings&#039;] = &#039;General settings&#039;;                                                                                    &lt;br /&gt;
// The name of our plugin.                                                                                                          &lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Photo&#039;;                                                                                                    &lt;br /&gt;
// Preset files setting.                                                                                                            &lt;br /&gt;
$string[&#039;presetfiles&#039;] = &#039;Additional theme preset files&#039;;                                                                           &lt;br /&gt;
// Preset files help text.                                                                                                          &lt;br /&gt;
$string[&#039;presetfiles_desc&#039;] = &#039;Preset files can be used to dramatically alter the appearance of the theme. See &amp;lt;a href=https://docs.moodle.org/dev/Boost_Presets&amp;gt;Boost presets&amp;lt;/a&amp;gt; for information on creating and sharing your own preset files, and see the &amp;lt;a href=http://moodle.net/boost&amp;gt;Presets repository&amp;lt;/a&amp;gt; for presets that others have shared.&#039;;&lt;br /&gt;
// Preset setting.                                                                                                                  &lt;br /&gt;
$string[&#039;preset&#039;] = &#039;Theme preset&#039;;                                                                                                 &lt;br /&gt;
// Preset help text.                                                                                                                &lt;br /&gt;
$string[&#039;preset_desc&#039;] = &#039;Pick a preset to broadly change the look of the theme.&#039;;                                                  &lt;br /&gt;
// Raw SCSS setting.                                                                                                                &lt;br /&gt;
$string[&#039;rawscss&#039;] = &#039;Raw SCSS&#039;;                                                                                                    &lt;br /&gt;
// Raw SCSS setting help text.                                                                                                      &lt;br /&gt;
$string[&#039;rawscss_desc&#039;] = &#039;Use this field to provide SCSS or CSS code which will be injected at the end of the style sheet.&#039;;       &lt;br /&gt;
// Raw initial SCSS setting.                                                                                                        &lt;br /&gt;
$string[&#039;rawscsspre&#039;] = &#039;Raw initial SCSS&#039;;                                                                                         &lt;br /&gt;
// Raw initial SCSS setting help text.                                                                                              &lt;br /&gt;
$string[&#039;rawscsspre_desc&#039;] = &#039;In this field you can provide initialising SCSS code, it will be injected before everything else. Most of the time you will use this setting to define variables.&#039;;&lt;br /&gt;
// We need to include a lang string for each block region.                                                                          &lt;br /&gt;
$string[&#039;region-side-pre&#039;] = &#039;Right&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We aren&#039;t quite there yet as you will notice if you try and upload a preset file and then choose it. The &amp;quot;theme_boost_get_main_scss_content&amp;quot; function from Boost is expecting the preset files to be stored in a file area for theme_boost only. We need to add this function to our own theme and tweak it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is the function that returns the SCSS source for the main file in our theme. We override the boost version because          &lt;br /&gt;
// we want to allow presets uploaded to our own theme file area to be selected in the preset list.                                  &lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {                                                                                                   &lt;br /&gt;
    return theme_photo_get_main_scss_content($theme);                                                                               &lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        // This preset file was fetched from the file area for theme_photo and not theme_boost (see the line above).                &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}             &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Stop and try it out ===&lt;br /&gt;
So now what is working and what isn&#039;t. Well - everything should be working and you should have a nice new theme extending boost with it&#039;s own settings pages. When Boost gets updates for bug fixes your new theme will inherit those fixes as it inherits all the SCSS and templates from theme boost. In addition your new theme will accept preset files and supports all the same features and settings as boost, ready to add more.&lt;br /&gt;
&lt;br /&gt;
== Take it further ==&lt;br /&gt;
Now we have our very nice starting point we can start changing or adding features, customising templates and output or tweaking the SCSS.&lt;br /&gt;
&lt;br /&gt;
=== Add some new settings ===&lt;br /&gt;
&lt;br /&gt;
From this point in the tutorial we will start adding features to our theme to extend it and make it AWESOME!&lt;br /&gt;
&lt;br /&gt;
Lets start with a new setting to set a background image on the login page. As you saw earlier, our theme defines it&#039;s list of settings in a file called settings.php. See [[Admin settings]] for more information about adding admin settings to any plugin. All of the different kinds of admin settings can be found in lib/adminlib.php. In our case we will want to add a setting which allows an admin to upload an image file. This is an &amp;quot;admin_setting_configstoredfile&amp;quot; and we add it to our theme by adding this code to the settings.php file inside and at the end of the &amp;quot;if ($ADMIN-&amp;gt;fulltree) {&amp;quot; condition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    // Login page background setting.                                                                                               &lt;br /&gt;
    // We use variables for readability.                                                                                            &lt;br /&gt;
    $name = &#039;theme_photo/loginbackgroundimage&#039;;                                                                                     &lt;br /&gt;
    $title = get_string(&#039;loginbackgroundimage&#039;, &#039;theme_photo&#039;);                                                                     &lt;br /&gt;
    $description = get_string(&#039;loginbackgroundimage_desc&#039;, &#039;theme_photo&#039;);                                                          &lt;br /&gt;
    // This creates the new setting.                                                                                                &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;loginbackgroundimage&#039;);                             &lt;br /&gt;
    // This means that theme caches will automatically be cleared when this setting is changed.                                     &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    // We always have to add the setting to a page for it to have any effect.                                                       &lt;br /&gt;
    $page-&amp;gt;add($setting);       &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need to add new lang strings to our language file.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lang/en/theme_photo.php&amp;quot;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Background image for login page.                                                                                                 &lt;br /&gt;
$string[&#039;loginbackgroundimage&#039;] = &#039;Login page background image&#039;;                                                                    &lt;br /&gt;
// Background image for login page.                                                                                                 &lt;br /&gt;
$string[&#039;loginbackgroundimage_desc&#039;] = &#039;An image that will be stretched to fill the background of the login page.&#039;;                 &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have a new setting that lets us upload a file - but it doesn&#039;t actually do anything yet. We need to update the theme to set this image background on the login page.&lt;br /&gt;
&lt;br /&gt;
In order to change the SCSS for our theme we will add 2 additional SCSS files and include them before and after our main scss.&lt;br /&gt;
&lt;br /&gt;
We already have a function in our lib.php file which fetches the main SCSS for our theme. This is a good point to include additional SCSS files. We can add 2 lines to the end of this function to achieve this.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        // This preset file was fetched from the file area for theme_photo and not theme_boost (see the line above).                &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Pre CSS - this is loaded AFTER any prescss from the setting but before the main scss.                                        &lt;br /&gt;
    $pre = file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/photo/scss/pre.scss&#039;);                                                         &lt;br /&gt;
    // Post CSS - this is loaded AFTER the main scss but before the extra scss from the setting.                                    &lt;br /&gt;
    $post = file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/photo/scss/post.scss&#039;);                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Combine them together.                                                                                                       &lt;br /&gt;
    return $pre . &amp;quot;\n&amp;quot; . $scss . &amp;quot;\n&amp;quot; . $post;                                                                                      &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;scss/pre.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
// Pre SCSS for the theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;scss/post.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
// Post SCSS for the theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Why do we use pre and post SCSS? ====&lt;br /&gt;
SCSS/SASS is a powerful language for creating CSS. It supports variables, functions, loops just like php. For lots of information and an introduction to SCSS read about [https://en.wikipedia.org/wiki/Sass_(stylesheet_language) Sass on wikipedia]. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pre SCSS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In Boost we use many variables when creating style rules.&lt;br /&gt;
&lt;br /&gt;
When declaring a variable in SCSS - it is best practice to define it like this:&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
$mycoolcolour: #FF0 !default;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this means is - if this variable is not defined already - set it to the hex value &#039;#FF0&#039;;&lt;br /&gt;
&lt;br /&gt;
So by setting this variable in some PRE scss we can override the default value of this variable everywhere it is used. Boost is built with the [https://v4-alpha.getbootstrap.com/ Bootstrap 4 (Alpha 4)] CSS Framework. This is a framework which uses SCSS to provide many extremely useful layouts and components which can be reused without adding specific CSS rules to style every page. Because bootstrap consistently uses variables we can customise many of these components easily by setting the value of the variables before we include the Bootstrap SCSS files.&lt;br /&gt;
&lt;br /&gt;
Many variables are available in /theme/boost/scss/bootstrap/_variables.scss - as an example we can change the look of all buttons and input fields with this one variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
$border-radius: 8px;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Post SCSS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Post SCSS is useful for defining full CSS rules. Because they are included last, they override any previous matching selector with the same [https://en.wikipedia.org/wiki/Cascading_Style_Sheets#Specificity Specificity].&lt;br /&gt;
&lt;br /&gt;
=== Tips for customising Moodle with SCSS (or CSS) ===&lt;br /&gt;
Some handy things to know when you are new to theming is that Moodle adds some classes to every page that helps you target a specific page or set of pages with some style rules. &lt;br /&gt;
&lt;br /&gt;
If you inspect a moodle page and look at the body tag you will see a long list of classes e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code html&amp;gt;&lt;br /&gt;
&amp;lt;body id=&amp;quot;page-course-view-weeks&amp;quot; class=&amp;quot;format-weeks  path-course path-course-view safari dir-ltr lang-en yui-skin-sam yui3-skin-sam damyon-per-in-moodle-com--stable_master pagelayout-course course-11 context-497 category-1 drawer-open-left jsenabled&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can see from this example that each page gets an id. This is a simplified representation of the current page in the navigation. In this example we are looking at the course page and this course is using the weeks format. &lt;br /&gt;
&lt;br /&gt;
The classes on the body tag can also be used to target a page or set of pages.&lt;br /&gt;
* &amp;lt;code&amp;gt;format-weeks&amp;lt;/code&amp;gt; The course format&lt;br /&gt;
* &amp;lt;code&amp;gt;path-course path-course-view&amp;lt;/code&amp;gt; The parts of the bread-crumb leading up to the current page (The current page is what goes in the id)&lt;br /&gt;
* &amp;lt;code&amp;gt;safari&amp;lt;/code&amp;gt; Some server side guessing of the browser type - it&#039;s not accurate so I would not rely on it&lt;br /&gt;
* &amp;lt;code&amp;gt;dir-ltr&amp;lt;/code&amp;gt; The direction of the current language for the page ( dir-rtl for RTL languages )&lt;br /&gt;
* &amp;lt;code&amp;gt;lang-en&amp;lt;/code&amp;gt; The current language of the page&lt;br /&gt;
* &amp;lt;code&amp;gt;yui*&amp;lt;/code&amp;gt; Legacy yui classes - ignore these&lt;br /&gt;
* &amp;lt;code&amp;gt;damyon-per-in-moodle-com--stable_master&amp;lt;/code&amp;gt; The current hostname for the site + the site name&lt;br /&gt;
* &amp;lt;code&amp;gt;pagelayout-course&amp;lt;/code&amp;gt; The layout type for the current page&lt;br /&gt;
* &amp;lt;code&amp;gt;course-11&amp;lt;/code&amp;gt; The id of the current course&lt;br /&gt;
* &amp;lt;code&amp;gt;context-497&amp;lt;/code&amp;gt; The current context id&lt;br /&gt;
* &amp;lt;code&amp;gt;category-1&amp;lt;/code&amp;gt; The category for the current course&lt;br /&gt;
* &amp;lt;code&amp;gt;drawer-open-left&amp;lt;/code&amp;gt; Added / removed when the navigation drawer is opened / closed in Boost&lt;br /&gt;
* &amp;lt;code&amp;gt;jsenabled&amp;lt;/code&amp;gt; True if the browser supports javascript&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/dev/Themes_overview#.3Cbody.3E_CSS_id_and_classes Read about Body id and classes].&lt;br /&gt;
&lt;br /&gt;
In our example the page layout is the most useful here as we have a specific page layout for login pages. We can now craft a rule that applies a background image only to login pages using &amp;quot;body.pagelayout-login&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How do we refer to an image in SCSS ? ===&lt;br /&gt;
So now we can add a rule to the post.scss which will set the background image for the login page. First we need to know how to construct a url to the background images from our stylesheet. &lt;br /&gt;
&lt;br /&gt;
In stylesheets in Moodle we can use a special pix tag to refer to images from our theme. The rule to attach the background image looks like this:&lt;br /&gt;
&#039;&#039;scss/post.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
body.pagelayout-login {                                                                                                             &lt;br /&gt;
    background-image: url([[pix:theme_photo|loginbackgroundimage]]);                                                                &lt;br /&gt;
    background-size: cover;                                                                                                         &lt;br /&gt;
}                          &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are 2 important parts to this tag (the bit in square brackets). The first is &amp;quot;theme_photo&amp;quot;. In this case we are passing a component name, the image serving code in theme_config::resolve_image_location() will then look for an image file in several locations. One of these is in &amp;quot;$CFG-&amp;gt;dataroot/pix_plugins/$type/$plugin/$image&amp;quot;. We can use this to make sure the image gets served correctly by copying the file saved in the setting to this location every time it is updated. (There is an alterative way we could do this by implementing pluginfile.php in our theme - which you can read about in the [[File API]] ).&lt;br /&gt;
&lt;br /&gt;
If we had just passed the value &amp;quot;theme&amp;quot; the image serving code would have looked for the image in the &amp;quot;pix&amp;quot; folder of our theme.&lt;br /&gt;
&lt;br /&gt;
So - we need this final change to copy the image file into our dataroot each time the setting is changed.&lt;br /&gt;
&lt;br /&gt;
In the settings file we will update the callback to a new function which we will define in our lib.php.&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Login page background setting.                                                                                               &lt;br /&gt;
    // We use variables for readability.                                                                                            &lt;br /&gt;
    $name = &#039;theme_photo/loginbackgroundimage&#039;;                                                                                     &lt;br /&gt;
    $title = get_string(&#039;loginbackgroundimage&#039;, &#039;theme_photo&#039;);                                                                     &lt;br /&gt;
    $description = get_string(&#039;loginbackgroundimage_desc&#039;, &#039;theme_photo&#039;);                                                          &lt;br /&gt;
    // This creates the new setting.                                                                                                &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;loginbackgroundimage&#039;);                             &lt;br /&gt;
    // This function will copy the image into the data_root location it can be served from.                                         &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_photo_update_settings_images&#039;);                                                            &lt;br /&gt;
    // We always have to add the setting to a page for it to have any effect.                                                       &lt;br /&gt;
    $page-&amp;gt;add($setting);&lt;br /&gt;
    //This will commit the background image setting. If you do not add this line the Login page background setting will not be shown.&lt;br /&gt;
    $settings-&amp;gt;add($page);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_update_settings_images($settingname) {                                                                         &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // The setting name that was updated comes as a string like &#039;s_theme_photo_loginbackgroundimage&#039;.                               &lt;br /&gt;
    // We split it on &#039;_&#039; characters.                                                                                               &lt;br /&gt;
    $parts = explode(&#039;_&#039;, $settingname);                                                                                            &lt;br /&gt;
    // And get the last one to get the setting name..                                                                               &lt;br /&gt;
    $settingname = end($parts);                                                                                                     &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Admin settings are stored in system context.                                                                                 &lt;br /&gt;
    $syscontext = context_system::instance();                                                                                       &lt;br /&gt;
    // This is the component name the setting is stored in.                                                                         &lt;br /&gt;
    $component = &#039;theme_photo&#039;;                                                                                                     &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // This is the value of the admin setting which is the filename of the uploaded file.                                           &lt;br /&gt;
    $filename = get_config($component, $settingname);                                                                               &lt;br /&gt;
    // We extract the file extension because we want to preserve it.                                                                &lt;br /&gt;
    $extension = substr($filename, strrpos($filename, &#039;.&#039;) + 1);                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // This is the path in the moodle internal file system.                                                                         &lt;br /&gt;
    $fullpath = &amp;quot;/{$syscontext-&amp;gt;id}/{$component}/{$settingname}/0{$filename}&amp;quot;;                                                      &lt;br /&gt;
    // Get an instance of the moodle file storage.                                                                                  &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
    // This is an efficient way to get a file if we know the exact path.                                                            &lt;br /&gt;
    if ($file = $fs-&amp;gt;get_file_by_hash(sha1($fullpath))) {                                                                           &lt;br /&gt;
        // We got the stored file - copy it to dataroot.                                                                            &lt;br /&gt;
        // This location matches the searched for location in theme_config::resolve_image_location.                                 &lt;br /&gt;
        $pathname = $CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039; . $settingname . &#039;.&#039; . $extension;                                 &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // This pattern matches any previous files with maybe different file extensions.                                            &lt;br /&gt;
        $pathpattern = $CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039; . $settingname . &#039;.*&#039;;                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Make sure this dir exists.                                                                                               &lt;br /&gt;
        @mkdir($CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039;, $CFG-&amp;gt;directorypermissions, true);                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Delete any existing files for this setting.                                                                              &lt;br /&gt;
        foreach (glob($pathpattern) as $filename) {                                                                                 &lt;br /&gt;
            @unlink($filename);                                                                                                     &lt;br /&gt;
        }                                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Copy the current file to this location.                                                                                  &lt;br /&gt;
        $file-&amp;gt;copy_content_to($pathname);                                                                                          &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Reset theme caches.                                                                                                          &lt;br /&gt;
    theme_reset_all_caches();                                                                                                       &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To edit the setting go to &#039;&#039;&#039;Site Administration &amp;gt; Appearance &amp;gt; Photo &amp;gt; Advanced setting&#039;&#039;&#039;. You will now see the Login page background setting.&lt;br /&gt;
It is now easy to add a new background image setting for every layout type. I can re-use this theme_photo_update_settings_images callback for each one - so all I have to do is add the setting to the settings.php file, add the SCSS rule to the scss/post.scss file and add the lang strings to the language file.&lt;br /&gt;
&lt;br /&gt;
Thats it for this tutorial, but there are [[:Category:Themes| more Themes docs]] to browse.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Themes]]&lt;/div&gt;</summary>
		<author><name>Meeth</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Creating_a_theme_based_on_boost&amp;diff=57736</id>
		<title>Creating a theme based on boost</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Creating_a_theme_based_on_boost&amp;diff=57736"/>
		<updated>2020-07-30T11:01:07Z</updated>

		<summary type="html">&lt;p&gt;Meeth: /* Add some new settings */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 3.2}}&lt;br /&gt;
{{Template:Themes}}&lt;br /&gt;
&lt;br /&gt;
This is a tutorial for how to create a new theme in any version of Moodle from 3.2 and later.&lt;br /&gt;
&lt;br /&gt;
Moodle 3.2 introduced a new core theme named &amp;quot;Boost&amp;quot; which is a great starting point for themers wanting to build a modern Moodle theme utilising all the latest features available to themes in Moodle.  If you aren&#039;t sure where to start, then START HERE!  :-)&lt;br /&gt;
&lt;br /&gt;
== Getting started ==&lt;br /&gt;
What is a theme? A theme in Moodle is just another type of plugin that can be developed. Themes are responsible for setting up the structure of each page and have the ability to customise the output of any page in Moodle.&lt;br /&gt;
&lt;br /&gt;
This tutorial is based on a working theme named &amp;quot;theme_photo&amp;quot; you can download it or view the source code for it here: https://github.com/damyon/moodle-theme_photo&lt;br /&gt;
&lt;br /&gt;
=== Choosing a name ===&lt;br /&gt;
Your new theme will need a name. Try and think of something short and memorable - and make sure it is not a name that has already been used by someone else. A quick search on the moodle.org/plugins can save you a lot of work renaming things later.&lt;br /&gt;
&lt;br /&gt;
Lets call our new example theme &amp;quot;photo&amp;quot; as we will add some settings to allow &amp;quot;photos&amp;quot; in various places in Moodle.&lt;br /&gt;
&lt;br /&gt;
=== Starting files ===&lt;br /&gt;
As a plugin, themes must start with the basic structure of a plugin in Moodle. See https://docs.moodle.org/dev/Tutorial#The_skeleton_of_your_plugin for an overview of the files common to all plugins in Moodle.&lt;br /&gt;
&lt;br /&gt;
Following this guide we can start creating our theme. First we create the folder for the new theme under &amp;quot;/theme/&amp;quot; folder in the Moodle root directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
/theme/photo/&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we need to add some standard plugin files to our theme. First is version.php&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/theme/photo/version.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the version of the plugin.                                                                                               &lt;br /&gt;
$plugin-&amp;gt;version = &#039;2016102100&#039;;                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the version of Moodle this plugin requires.                                                                              &lt;br /&gt;
$plugin-&amp;gt;requires = &#039;2016070700&#039;;                                                                                                   &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the component name of the plugin - it always starts with &#039;theme_&#039;                                                        &lt;br /&gt;
// for themes and should be the same as the name of the folder.                                                                     &lt;br /&gt;
$plugin-&amp;gt;component = &#039;theme_photo&#039;;                                                                                                 &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a list of plugins, this plugin depends on (and their versions).                                                          &lt;br /&gt;
$plugin-&amp;gt;dependencies = [                                                                                                           &lt;br /&gt;
    &#039;theme_boost&#039; =&amp;gt; &#039;2016102100&#039;                                                                                                   &lt;br /&gt;
];                                                                              &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need a language file so that all our strings can be translated into different languages. The name of this file is the component name of our plugin and it sits in the lang/en/ folder for our plugin. We can include translations of our plugin, but we can also provide translations via the https://lang.moodle.org/ website once our plugin has been published to the plugins database at http://www.moodle.org/plugins/.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/theme/photo/lang/en/theme_photo.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// A description shown in the admin theme selector.                                                                                 &lt;br /&gt;
$string[&#039;choosereadme&#039;] = &#039;Theme photo is a child theme of Boost. It adds the ability to upload background photos.&#039;;                &lt;br /&gt;
// The name of our plugin.                                                                                                          &lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Photo&#039;;                                                                                                    &lt;br /&gt;
// We need to include a lang string for each block region.                                                                          &lt;br /&gt;
$string[&#039;region-side-pre&#039;] = &#039;Right&#039;;                                         &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Theme specific files ===&lt;br /&gt;
Theme plugins have a few more standard files they need to define. &lt;br /&gt;
&lt;br /&gt;
Themes require a favicon file to show in the address bar. See [[http://docs.moodle.org/en/Favicon Favicon]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;pix/favicon.ico&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(Image file not shown).&lt;br /&gt;
&lt;br /&gt;
Themes also require an example screenshot to be displayed in the theme selector.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;pix/screenshot.jpg&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(Image file not shown).&lt;br /&gt;
&lt;br /&gt;
Themes require a lib.php file. This file contains callbacks used by various API&#039;s in Moodle. Initially this file can be empty, but as we add features to our theme we will need to add some functions here.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
// We will add callbacks here as we add features to our theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Theme config goes in a config.php file. This is one of the most important files in our theme. Once we add this file we will be ready to test our theme for the first time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
// $THEME is defined before this page is included and we can define settings by adding properties to this global object.            &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// The first setting we need is the name of the theme. This should be the last part of the component name, and the same             &lt;br /&gt;
// as the directory name for our theme.                                                                                             &lt;br /&gt;
$THEME-&amp;gt;name = &#039;photo&#039;;                                                                                                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This setting list the style sheets we want to include in our theme. Because we want to use SCSS instead of CSS - we won&#039;t        &lt;br /&gt;
// list any style sheets. If we did we would list the name of a file in the /style/ folder for our theme without any css file      &lt;br /&gt;
// extensions.                                                                                                                      &lt;br /&gt;
$THEME-&amp;gt;sheets = [];                                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a setting that can be used to provide some styling to the content in the TinyMCE text editor. This is no longer the      &lt;br /&gt;
// default text editor and &amp;quot;Atto&amp;quot; does not need this setting so we won&#039;t provide anything. If we did it would work the same         &lt;br /&gt;
// as the previous setting - listing a file in the /styles/ folder.                                                                 &lt;br /&gt;
$THEME-&amp;gt;editor_sheets = [];                                                                                                         &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a critical setting. We want to inherit from theme_boost because it provides a great starting point for SCSS bootstrap4   &lt;br /&gt;
// themes. We could add more than one parent here to inherit from multiple parents, and if we did they would be processed in        &lt;br /&gt;
// order of importance (later themes overriding earlier ones). Things we will inherit from the parent theme include                 &lt;br /&gt;
// styles and mustache templates and some (not all) settings.                                                                       &lt;br /&gt;
$THEME-&amp;gt;parents = [&#039;boost&#039;];                                                                                                        &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// A dock is a way to take blocks out of the page and put them in a persistent floating area on the side of the page. Boost         &lt;br /&gt;
// does not support a dock so we won&#039;t either - but look at bootstrapbase for an example of a theme with a dock.                    &lt;br /&gt;
$THEME-&amp;gt;enable_dock = false;                                                                                                        &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is an old setting used to load specific CSS for some YUI JS. We don&#039;t need it in Boost based themes because Boost           &lt;br /&gt;
// provides default styling for the YUI modules that we use. It is not recommended to use this setting anymore.                     &lt;br /&gt;
$THEME-&amp;gt;yuicssmodules = array();                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// Most themes will use this rendererfactory as this is the one that allows the theme to override any other renderer.               &lt;br /&gt;
$THEME-&amp;gt;rendererfactory = &#039;theme_overridden_renderer_factory&#039;;                                                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a list of blocks that are required to exist on all pages for this theme to function correctly. For example               &lt;br /&gt;
// bootstrap base requires the settings and navigation blocks because otherwise there would be no way to navigate to all the        &lt;br /&gt;
// pages in Moodle. Boost does not require these blocks because it provides other ways to navigate built into the theme.            &lt;br /&gt;
$THEME-&amp;gt;requiredblocks = &#039;&#039;;   &lt;br /&gt;
&lt;br /&gt;
// This is a feature that tells the blocks library not to use the &amp;quot;Add a block&amp;quot; block. We don&#039;t want this in boost based themes because&lt;br /&gt;
// it forces a block region into the page when editing is enabled and it takes up too much room.&lt;br /&gt;
$THEME-&amp;gt;addblockposition = BLOCK_ADDBLOCK_POSITION_FLATNAV;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ready set go! ===&lt;br /&gt;
If you have been following along - now we are at the point where we can actually install and test our new theme. Try it now by visiting the admin notifications page to install the new plugin, and then choosing the new theme from the theme selector.&lt;br /&gt;
&lt;br /&gt;
[[https://docs.moodle.org/en/Standard_themes#Theme_selector Theme selector]]&lt;br /&gt;
&lt;br /&gt;
When you choose the new theme - you will find that it looks exactly the same as Boost. At this point with our minimal configuration - we are inheriting almost everything from our parent theme including styles and templates. You will notice though that we don&#039;t inherit the settings from our parent theme. If you choose a different preset in Boost - it is not applied in this child theme.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&lt;br /&gt;
Note: make sure your config.php file contains $THEME-&amp;gt;hidefromselector = false; (or at least set to false) or else, your theme wont show up in theme selector.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What if I want the settings too? ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&lt;br /&gt;
This section is included for completeness - but it is not recommended for themes to utilise settings from their parents. To find out how to duplicate the settings from the parent theme so they operate independently skip to [[#Duplicate the settings from Boost]].&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If I want the settings from Boost to apply to my child theme as well I need to know a bit about how each of the settings in Boost is applied to make them work in my child theme.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Setting 1 - preset.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;preset&amp;quot; file is the file that is used as the main file for scss compilation. In Boost this is controlled by the theme config value:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {&lt;br /&gt;
    return theme_boost_get_main_scss_content($theme);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_boost&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this function is doing is checking for a theme setting &amp;quot;preset&amp;quot; and either fetching the file from Moodles internal file storage, or from the /preset/ folder. The function then returns the contents of this file.&lt;br /&gt;
&lt;br /&gt;
It does not automatically work for our child theme because we have no setting named &amp;quot;preset&amp;quot; in our child theme and this code is not searching the theme parents for the setting. If we wanted it to apply we could do this in our child theme:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This setting defines the main scss file for our theme to be compiled. We could set it to a static file in the scss folder or to a function which returns the SCSS based on theme settings.&lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {&lt;br /&gt;
&lt;br /&gt;
    // We need to load the config for our parent theme because that is where the preset setting is defined.&lt;br /&gt;
    $parentconfig = theme_config::load(&#039;boost&#039;);&lt;br /&gt;
    // Call a function from our parent themes lib.php file to fetch the content of the themes main SCSS file based on it&#039;s own config, not ours.&lt;br /&gt;
    return theme_boost_get_main_scss_content($parentconfig);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings 2+3 brandcolor + scsspre&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The way these settings work is they generate a chunk of SCSS to be prepended to the main scss file. In boost they work like this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;prescsscallback = &#039;theme_boost_get_pre_scss&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_pre_scss($theme) {                                                                                         &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $configurable = [                                                                                                               &lt;br /&gt;
        // Config key =&amp;gt; [variableName, ...].                                                                                       &lt;br /&gt;
        &#039;brandcolor&#039; =&amp;gt; [&#039;brand-primary&#039;],                                                                                          &lt;br /&gt;
    ];                                                                                                                              &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Prepend variables first.                                                                                                     &lt;br /&gt;
    foreach ($configurable as $configkey =&amp;gt; $targets) {                                                                             &lt;br /&gt;
        $value = isset($theme-&amp;gt;settings-&amp;gt;{$configkey}) ? $theme-&amp;gt;settings-&amp;gt;{$configkey} : null;                                     &lt;br /&gt;
        if (empty($value)) {                                                                                                        &lt;br /&gt;
            continue;                                                                                                               &lt;br /&gt;
        }                                                                                                                           &lt;br /&gt;
        array_map(function($target) use (&amp;amp;$scss, $value) {                                                                          &lt;br /&gt;
            $scss .= &#039;$&#039; . $target . &#039;: &#039; . $value . &amp;quot;;\n&amp;quot;;                                                                         &lt;br /&gt;
        }, (array) $targets);                                                                                                       &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Prepend pre-scss.                                                                                                            &lt;br /&gt;
    if (!empty($theme-&amp;gt;settings-&amp;gt;scsspre)) {                                                                                        &lt;br /&gt;
        $scss .= $theme-&amp;gt;settings-&amp;gt;scsspre;                                                                                         &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}  &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this code is doing is: &lt;br /&gt;
* looping over a list of theme settings that map to a SCSS variable and building some SCSS to initialise that variable from the setting. In Boost there is only one * brandprimary - but if we wanted to expose more bootstrap variables as theme settings we could use this function as a template in our child theme and add more settings to the $configurable array.&lt;br /&gt;
* Adding all of the raw SCSS from the scsspre theme setting&lt;br /&gt;
* Returning the whole thing as a string to be added before the main scss file.&lt;br /&gt;
&lt;br /&gt;
If we want this code to work in our child theme, using the settings from Boost we could do this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is a function that returns some SCSS as a string to prepend to the main SCSS file.                                          &lt;br /&gt;
$THEME-&amp;gt;prescsscallback = &#039;theme_photo_get_pre_scss&#039;;               &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Function to return the SCSS to prepend to our main SCSS for this theme.&lt;br /&gt;
// Note the function name starts with the component name because this is a global function and we don&#039;t want namespace clashes.&lt;br /&gt;
function theme_photo_get_pre_scss($theme) {&lt;br /&gt;
    // Load the settings from the parent.                                                                                           &lt;br /&gt;
    $theme = theme_config::load(&#039;boost&#039;);                                                                                           &lt;br /&gt;
    // Call the parent themes get_pre_scss function.                                                                                &lt;br /&gt;
    return theme_boost_get_pre_scss($theme);                         &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Setting 4 scss (post)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The final setting from Boost is a raw text field which adds SCSS to the end of the main SCSS file. This is a useful place to add style rules as they will override previously defined styles with the same specificity. It is applied in Boost by the following lines:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;extrascsscallback = &#039;theme_boost_get_extra_scss&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_extra_scss($theme) {                                                                                       &lt;br /&gt;
    return !empty($theme-&amp;gt;settings-&amp;gt;scss) ? $theme-&amp;gt;settings-&amp;gt;scss : &#039;&#039;;                                                            &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is just returning the value of the setting as a string.&lt;br /&gt;
&lt;br /&gt;
To make this setting apply in our child theme too - we use similar code to the previous sections.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is a function that returns some SCSS as a string to append to the main SCSS file.                                          &lt;br /&gt;
$THEME-&amp;gt;extrascsscallback = &#039;theme_photo_get_extra_scss&#039;;               &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Function to return the SCSS to append to our main SCSS for this theme.&lt;br /&gt;
// Note the function name starts with the component name because this is a global function and we don&#039;t want namespace clashes.&lt;br /&gt;
function theme_photo_get_extra_scss($theme) {&lt;br /&gt;
    // Load the settings from the parent.                                                                                           &lt;br /&gt;
    $theme = theme_config::load(&#039;boost&#039;);                                                                                           &lt;br /&gt;
    // Call the parent themes get_extra_scss function.                                                                                &lt;br /&gt;
    return theme_boost_get_extra_scss($theme);                         &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Duplicate the settings from Boost  ===&lt;br /&gt;
&lt;br /&gt;
This is the recommended way to extend boost as your child theme will not be affected by changes to the Boost settings, and both themes can be in use with different settings applied.&lt;br /&gt;
&lt;br /&gt;
All that needs to happen is to create theme settings in the child theme that match each of the settings in the parent theme. You will need to add matching language strings for each of these settings in the language file.&lt;br /&gt;
&lt;br /&gt;
This example shows how to do it - We are re-using the nice looking theme_boost_admin_settingspage_tabs class from boost and creating duplicate versions of each of the settings.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is used for performance, we don&#039;t need to know about these settings on every page in Moodle, only when                      &lt;br /&gt;
// we are looking at the admin settings pages.                                                                                      &lt;br /&gt;
if ($ADMIN-&amp;gt;fulltree) {                                                                                                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Boost provides a nice setting page which splits settings onto separate tabs. We want to use it here.                         &lt;br /&gt;
    $settings = new theme_boost_admin_settingspage_tabs(&#039;themesettingphoto&#039;, get_string(&#039;configtitle&#039;, &#039;theme_photo&#039;));             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Each page is a tab - the first is the &amp;quot;General&amp;quot; tab.                                                                         &lt;br /&gt;
    $page = new admin_settingpage(&#039;theme_photo_general&#039;, get_string(&#039;generalsettings&#039;, &#039;theme_photo&#039;));                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Replicate the preset setting from boost.                                                                                     &lt;br /&gt;
    $name = &#039;theme_photo/preset&#039;;                                                                                                   &lt;br /&gt;
    $title = get_string(&#039;preset&#039;, &#039;theme_photo&#039;);                                                                                   &lt;br /&gt;
    $description = get_string(&#039;preset_desc&#039;, &#039;theme_photo&#039;);                                                                        &lt;br /&gt;
    $default = &#039;default.scss&#039;;                                                                                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // We list files in our own file area to add to the drop down. We will provide our own function to                              &lt;br /&gt;
    // load all the presets from the correct paths.                                                                                 &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
    $files = $fs-&amp;gt;get_area_files($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;itemid, filepath, filename&#039;, false);                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $choices = [];                                                                                                                  &lt;br /&gt;
    foreach ($files as $file) {                                                                                                     &lt;br /&gt;
        $choices[$file-&amp;gt;get_filename()] = $file-&amp;gt;get_filename();                                                                    &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
    // These are the built in presets from Boost.                                                                                   &lt;br /&gt;
    $choices[&#039;default.scss&#039;] = &#039;default.scss&#039;;                                                                                      &lt;br /&gt;
    $choices[&#039;plain.scss&#039;] = &#039;plain.scss&#039;;                                                                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $setting = new admin_setting_configselect($name, $title, $description, $default, $choices);                                     &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Preset files setting.                                                                                                        &lt;br /&gt;
    $name = &#039;theme_photo/presetfiles&#039;;                                                                                              &lt;br /&gt;
    $title = get_string(&#039;presetfiles&#039;,&#039;theme_photo&#039;);                                                                               &lt;br /&gt;
    $description = get_string(&#039;presetfiles_desc&#039;, &#039;theme_photo&#039;);                                                                   &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;preset&#039;, 0,                                         &lt;br /&gt;
        array(&#039;maxfiles&#039; =&amp;gt; 20, &#039;accepted_types&#039; =&amp;gt; array(&#039;.scss&#039;)));                                                               &lt;br /&gt;
    $page-&amp;gt;add($setting);     &lt;br /&gt;
&lt;br /&gt;
    // Variable $brand-color.                                                                                                       &lt;br /&gt;
    // We use an empty default value because the default colour should come from the preset.                                        &lt;br /&gt;
    $name = &#039;theme_photo/brandcolor&#039;;                                                                                               &lt;br /&gt;
    $title = get_string(&#039;brandcolor&#039;, &#039;theme_photo&#039;);                                                                               &lt;br /&gt;
    $description = get_string(&#039;brandcolor_desc&#039;, &#039;theme_photo&#039;);                                                                    &lt;br /&gt;
    $setting = new admin_setting_configcolourpicker($name, $title, $description, &#039;&#039;);                                               &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Must add the page after definiting all the settings!                                                                         &lt;br /&gt;
    $settings-&amp;gt;add($page);                                                                                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Advanced settings.                                                                                                           &lt;br /&gt;
    $page = new admin_settingpage(&#039;theme_photo_advanced&#039;, get_string(&#039;advancedsettings&#039;, &#039;theme_photo&#039;));                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Raw SCSS to include before the content.                                                                                      &lt;br /&gt;
    $setting = new admin_setting_configtextarea(&#039;theme_photo/scsspre&#039;,                                                              &lt;br /&gt;
        get_string(&#039;rawscsspre&#039;, &#039;theme_photo&#039;), get_string(&#039;rawscsspre_desc&#039;, &#039;theme_photo&#039;), &#039;&#039;, PARAM_RAW);                      &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Raw SCSS to include after the content.                                                                                       &lt;br /&gt;
    $setting = new admin_setting_configtextarea(&#039;theme_photo/scss&#039;, get_string(&#039;rawscss&#039;, &#039;theme_photo&#039;),                           &lt;br /&gt;
        get_string(&#039;rawscss_desc&#039;, &#039;theme_photo&#039;), &#039;&#039;, PARAM_RAW);                                                                  &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $settings-&amp;gt;add($page);                                                                                                          &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lang/en/theme_photo.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
// The name of the second tab in the theme settings.                                                                                &lt;br /&gt;
$string[&#039;advancedsettings&#039;] = &#039;Advanced settings&#039;;                                                                                  &lt;br /&gt;
// The brand colour setting.                                                                                                        &lt;br /&gt;
$string[&#039;brandcolor&#039;] = &#039;Brand colour&#039;;                                                                                             &lt;br /&gt;
// The brand colour setting description.                                                                                            &lt;br /&gt;
$string[&#039;brandcolor_desc&#039;] = &#039;The accent colour.&#039;;     &lt;br /&gt;
// A description shown in the admin theme selector.                                                                                 &lt;br /&gt;
$string[&#039;choosereadme&#039;] = &#039;Theme photo is a child theme of Boost. It adds the ability to upload background photos.&#039;;                &lt;br /&gt;
// Name of the settings pages.                                                                                                      &lt;br /&gt;
$string[&#039;configtitle&#039;] = &#039;Photo settings&#039;;                                                                                          &lt;br /&gt;
// Name of the first settings tab.                                                                                                  &lt;br /&gt;
$string[&#039;generalsettings&#039;] = &#039;General settings&#039;;                                                                                    &lt;br /&gt;
// The name of our plugin.                                                                                                          &lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Photo&#039;;                                                                                                    &lt;br /&gt;
// Preset files setting.                                                                                                            &lt;br /&gt;
$string[&#039;presetfiles&#039;] = &#039;Additional theme preset files&#039;;                                                                           &lt;br /&gt;
// Preset files help text.                                                                                                          &lt;br /&gt;
$string[&#039;presetfiles_desc&#039;] = &#039;Preset files can be used to dramatically alter the appearance of the theme. See &amp;lt;a href=https://docs.moodle.org/dev/Boost_Presets&amp;gt;Boost presets&amp;lt;/a&amp;gt; for information on creating and sharing your own preset files, and see the &amp;lt;a href=http://moodle.net/boost&amp;gt;Presets repository&amp;lt;/a&amp;gt; for presets that others have shared.&#039;;&lt;br /&gt;
// Preset setting.                                                                                                                  &lt;br /&gt;
$string[&#039;preset&#039;] = &#039;Theme preset&#039;;                                                                                                 &lt;br /&gt;
// Preset help text.                                                                                                                &lt;br /&gt;
$string[&#039;preset_desc&#039;] = &#039;Pick a preset to broadly change the look of the theme.&#039;;                                                  &lt;br /&gt;
// Raw SCSS setting.                                                                                                                &lt;br /&gt;
$string[&#039;rawscss&#039;] = &#039;Raw SCSS&#039;;                                                                                                    &lt;br /&gt;
// Raw SCSS setting help text.                                                                                                      &lt;br /&gt;
$string[&#039;rawscss_desc&#039;] = &#039;Use this field to provide SCSS or CSS code which will be injected at the end of the style sheet.&#039;;       &lt;br /&gt;
// Raw initial SCSS setting.                                                                                                        &lt;br /&gt;
$string[&#039;rawscsspre&#039;] = &#039;Raw initial SCSS&#039;;                                                                                         &lt;br /&gt;
// Raw initial SCSS setting help text.                                                                                              &lt;br /&gt;
$string[&#039;rawscsspre_desc&#039;] = &#039;In this field you can provide initialising SCSS code, it will be injected before everything else. Most of the time you will use this setting to define variables.&#039;;&lt;br /&gt;
// We need to include a lang string for each block region.                                                                          &lt;br /&gt;
$string[&#039;region-side-pre&#039;] = &#039;Right&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We aren&#039;t quite there yet as you will notice if you try and upload a preset file and then choose it. The &amp;quot;theme_boost_get_main_scss_content&amp;quot; function from Boost is expecting the preset files to be stored in a file area for theme_boost only. We need to add this function to our own theme and tweak it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is the function that returns the SCSS source for the main file in our theme. We override the boost version because          &lt;br /&gt;
// we want to allow presets uploaded to our own theme file area to be selected in the preset list.                                  &lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {                                                                                                   &lt;br /&gt;
    return theme_photo_get_main_scss_content($theme);                                                                               &lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        // This preset file was fetched from the file area for theme_photo and not theme_boost (see the line above).                &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}             &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Stop and try it out ===&lt;br /&gt;
So now what is working and what isn&#039;t. Well - everything should be working and you should have a nice new theme extending boost with it&#039;s own settings pages. When Boost gets updates for bug fixes your new theme will inherit those fixes as it inherits all the SCSS and templates from theme boost. In addition your new theme will accept preset files and supports all the same features and settings as boost, ready to add more.&lt;br /&gt;
&lt;br /&gt;
== Take it further ==&lt;br /&gt;
Now we have our very nice starting point we can start changing or adding features, customising templates and output or tweaking the SCSS.&lt;br /&gt;
&lt;br /&gt;
=== Add some new settings ===&lt;br /&gt;
&lt;br /&gt;
From this point in the tutorial we will start adding features to our theme to extend it and make it AWESOME!&lt;br /&gt;
&lt;br /&gt;
Lets start with a new setting to set a background image on the login page. As you saw earlier, our theme defines it&#039;s list of settings in a file called settings.php. See [[Admin settings]] for more information about adding admin settings to any plugin. All of the different kinds of admin settings can be found in lib/adminlib.php. In our case we will want to add a setting which allows an admin to upload an image file. This is an &amp;quot;admin_setting_configstoredfile&amp;quot; and we add it to our theme by adding this code to the settings.php file inside and at the end of the &amp;quot;if ($ADMIN-&amp;gt;fulltree) {&amp;quot; condition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    // Login page background setting.                                                                                               &lt;br /&gt;
    // We use variables for readability.                                                                                            &lt;br /&gt;
    $name = &#039;theme_photo/loginbackgroundimage&#039;;                                                                                     &lt;br /&gt;
    $title = get_string(&#039;loginbackgroundimage&#039;, &#039;theme_photo&#039;);                                                                     &lt;br /&gt;
    $description = get_string(&#039;loginbackgroundimage_desc&#039;, &#039;theme_photo&#039;);                                                          &lt;br /&gt;
    // This creates the new setting.                                                                                                &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;loginbackgroundimage&#039;);                             &lt;br /&gt;
    // This means that theme caches will automatically be cleared when this setting is changed.                                     &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    // We always have to add the setting to a page for it to have any effect.                                                       &lt;br /&gt;
    $page-&amp;gt;add($setting);       &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need to add new lang strings to our language file.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lang/en/theme_photo.php&amp;quot;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Background image for login page.                                                                                                 &lt;br /&gt;
$string[&#039;loginbackgroundimage&#039;] = &#039;Login page background image&#039;;                                                                    &lt;br /&gt;
// Background image for login page.                                                                                                 &lt;br /&gt;
$string[&#039;loginbackgroundimage_desc&#039;] = &#039;An image that will be stretched to fill the background of the login page.&#039;;                 &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have a new setting that lets us upload a file - but it doesn&#039;t actually do anything yet. We need to update the theme to set this image background on the login page.&lt;br /&gt;
&lt;br /&gt;
In order to change the SCSS for our theme we will add 2 additional SCSS files and include them before and after our main scss.&lt;br /&gt;
&lt;br /&gt;
We already have a function in our lib.php file which fetches the main SCSS for our theme. This is a good point to include additional SCSS files. We can add 2 lines to the end of this function to achieve this.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        // This preset file was fetched from the file area for theme_photo and not theme_boost (see the line above).                &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Pre CSS - this is loaded AFTER any prescss from the setting but before the main scss.                                        &lt;br /&gt;
    $pre = file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/photo/scss/pre.scss&#039;);                                                         &lt;br /&gt;
    // Post CSS - this is loaded AFTER the main scss but before the extra scss from the setting.                                    &lt;br /&gt;
    $post = file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/photo/scss/post.scss&#039;);                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Combine them together.                                                                                                       &lt;br /&gt;
    return $pre . &amp;quot;\n&amp;quot; . $scss . &amp;quot;\n&amp;quot; . $post;                                                                                      &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;scss/pre.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
// Pre SCSS for the theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;scss/post.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
// Post SCSS for the theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Why do we use pre and post SCSS? ====&lt;br /&gt;
SCSS/SASS is a powerful language for creating CSS. It supports variables, functions, loops just like php. For lots of information and an introduction to SCSS read about [https://en.wikipedia.org/wiki/Sass_(stylesheet_language) Sass on wikipedia]. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pre SCSS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In Boost we use many variables when creating style rules.&lt;br /&gt;
&lt;br /&gt;
When declaring a variable in SCSS - it is best practice to define it like this:&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
$mycoolcolour: #FF0 !default;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this means is - if this variable is not defined already - set it to the hex value &#039;#FF0&#039;;&lt;br /&gt;
&lt;br /&gt;
So by setting this variable in some PRE scss we can override the default value of this variable everywhere it is used. Boost is built with the [https://v4-alpha.getbootstrap.com/ Bootstrap 4 (Alpha 4)] CSS Framework. This is a framework which uses SCSS to provide many extremely useful layouts and components which can be reused without adding specific CSS rules to style every page. Because bootstrap consistently uses variables we can customise many of these components easily by setting the value of the variables before we include the Bootstrap SCSS files.&lt;br /&gt;
&lt;br /&gt;
Many variables are available in /theme/boost/scss/bootstrap/_variables.scss - as an example we can change the look of all buttons and input fields with this one variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
$border-radius: 8px;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Post SCSS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Post SCSS is useful for defining full CSS rules. Because they are included last, they override any previous matching selector with the same [https://en.wikipedia.org/wiki/Cascading_Style_Sheets#Specificity Specificity].&lt;br /&gt;
&lt;br /&gt;
=== Tips for customising Moodle with SCSS (or CSS) ===&lt;br /&gt;
Some handy things to know when you are new to theming is that Moodle adds some classes to every page that helps you target a specific page or set of pages with some style rules. &lt;br /&gt;
&lt;br /&gt;
If you inspect a moodle page and look at the body tag you will see a long list of classes e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code html&amp;gt;&lt;br /&gt;
&amp;lt;body id=&amp;quot;page-course-view-weeks&amp;quot; class=&amp;quot;format-weeks  path-course path-course-view safari dir-ltr lang-en yui-skin-sam yui3-skin-sam damyon-per-in-moodle-com--stable_master pagelayout-course course-11 context-497 category-1 drawer-open-left jsenabled&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can see from this example that each page gets an id. This is a simplified representation of the current page in the navigation. In this example we are looking at the course page and this course is using the weeks format. &lt;br /&gt;
&lt;br /&gt;
The classes on the body tag can also be used to target a page or set of pages.&lt;br /&gt;
* &amp;lt;code&amp;gt;format-weeks&amp;lt;/code&amp;gt; The course format&lt;br /&gt;
* &amp;lt;code&amp;gt;path-course path-course-view&amp;lt;/code&amp;gt; The parts of the bread-crumb leading up to the current page (The current page is what goes in the id)&lt;br /&gt;
* &amp;lt;code&amp;gt;safari&amp;lt;/code&amp;gt; Some server side guessing of the browser type - it&#039;s not accurate so I would not rely on it&lt;br /&gt;
* &amp;lt;code&amp;gt;dir-ltr&amp;lt;/code&amp;gt; The direction of the current language for the page ( dir-rtl for RTL languages )&lt;br /&gt;
* &amp;lt;code&amp;gt;lang-en&amp;lt;/code&amp;gt; The current language of the page&lt;br /&gt;
* &amp;lt;code&amp;gt;yui*&amp;lt;/code&amp;gt; Legacy yui classes - ignore these&lt;br /&gt;
* &amp;lt;code&amp;gt;damyon-per-in-moodle-com--stable_master&amp;lt;/code&amp;gt; The current hostname for the site + the site name&lt;br /&gt;
* &amp;lt;code&amp;gt;pagelayout-course&amp;lt;/code&amp;gt; The layout type for the current page&lt;br /&gt;
* &amp;lt;code&amp;gt;course-11&amp;lt;/code&amp;gt; The id of the current course&lt;br /&gt;
* &amp;lt;code&amp;gt;context-497&amp;lt;/code&amp;gt; The current context id&lt;br /&gt;
* &amp;lt;code&amp;gt;category-1&amp;lt;/code&amp;gt; The category for the current course&lt;br /&gt;
* &amp;lt;code&amp;gt;drawer-open-left&amp;lt;/code&amp;gt; Added / removed when the navigation drawer is opened / closed in Boost&lt;br /&gt;
* &amp;lt;code&amp;gt;jsenabled&amp;lt;/code&amp;gt; True if the browser supports javascript&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/dev/Themes_overview#.3Cbody.3E_CSS_id_and_classes Read about Body id and classes].&lt;br /&gt;
&lt;br /&gt;
In our example the page layout is the most useful here as we have a specific page layout for login pages. We can now craft a rule that applies a background image only to login pages using &amp;quot;body.pagelayout-login&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How do we refer to an image in SCSS ? ===&lt;br /&gt;
So now we can add a rule to the post.scss which will set the background image for the login page. First we need to know how to construct a url to the background images from our stylesheet. &lt;br /&gt;
&lt;br /&gt;
In stylesheets in Moodle we can use a special pix tag to refer to images from our theme. The rule to attach the background image looks like this:&lt;br /&gt;
&#039;&#039;scss/post.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
body.pagelayout-login {                                                                                                             &lt;br /&gt;
    background-image: url([[pix:theme_photo|loginbackgroundimage]]);                                                                &lt;br /&gt;
    background-size: cover;                                                                                                         &lt;br /&gt;
}                          &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are 2 important parts to this tag (the bit in square brackets). The first is &amp;quot;theme_photo&amp;quot;. In this case we are passing a component name, the image serving code in theme_config::resolve_image_location() will then look for an image file in several locations. One of these is in &amp;quot;$CFG-&amp;gt;dataroot/pix_plugins/$type/$plugin/$image&amp;quot;. We can use this to make sure the image gets served correctly by copying the file saved in the setting to this location every time it is updated. (There is an alterative way we could do this by implementing pluginfile.php in our theme - which you can read about in the [[File API]] ).&lt;br /&gt;
&lt;br /&gt;
If we had just passed the value &amp;quot;theme&amp;quot; the image serving code would have looked for the image in the &amp;quot;pix&amp;quot; folder of our theme.&lt;br /&gt;
&lt;br /&gt;
So - we need this final change to copy the image file into our dataroot each time the setting is changed.&lt;br /&gt;
&lt;br /&gt;
In the settings file we will update the callback to a new function which we will define in our lib.php.&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Login page background setting.                                                                                               &lt;br /&gt;
    // We use variables for readability.                                                                                            &lt;br /&gt;
    $name = &#039;theme_photo/loginbackgroundimage&#039;;                                                                                     &lt;br /&gt;
    $title = get_string(&#039;loginbackgroundimage&#039;, &#039;theme_photo&#039;);                                                                     &lt;br /&gt;
    $description = get_string(&#039;loginbackgroundimage_desc&#039;, &#039;theme_photo&#039;);                                                          &lt;br /&gt;
    // This creates the new setting.                                                                                                &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;loginbackgroundimage&#039;);                             &lt;br /&gt;
    // This function will copy the image into the data_root location it can be served from.                                         &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_photo_update_settings_images&#039;);                                                            &lt;br /&gt;
    // We always have to add the setting to a page for it to have any effect.                                                       &lt;br /&gt;
    $page-&amp;gt;add($setting);&lt;br /&gt;
    //This will commit the background image setting. If you do not add this line the Login page background setting will not be shown.&lt;br /&gt;
    $settings-&amp;gt;add($page);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_update_settings_images($settingname) {                                                                         &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // The setting name that was updated comes as a string like &#039;s_theme_photo_loginbackgroundimage&#039;.                               &lt;br /&gt;
    // We split it on &#039;_&#039; characters.                                                                                               &lt;br /&gt;
    $parts = explode(&#039;_&#039;, $settingname);                                                                                            &lt;br /&gt;
    // And get the last one to get the setting name..                                                                               &lt;br /&gt;
    $settingname = end($parts);                                                                                                     &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Admin settings are stored in system context.                                                                                 &lt;br /&gt;
    $syscontext = context_system::instance();                                                                                       &lt;br /&gt;
    // This is the component name the setting is stored in.                                                                         &lt;br /&gt;
    $component = &#039;theme_photo&#039;;                                                                                                     &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // This is the value of the admin setting which is the filename of the uploaded file.                                           &lt;br /&gt;
    $filename = get_config($component, $settingname);                                                                               &lt;br /&gt;
    // We extract the file extension because we want to preserve it.                                                                &lt;br /&gt;
    $extension = substr($filename, strrpos($filename, &#039;.&#039;) + 1);                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // This is the path in the moodle internal file system.                                                                         &lt;br /&gt;
    $fullpath = &amp;quot;/{$syscontext-&amp;gt;id}/{$component}/{$settingname}/0{$filename}&amp;quot;;                                                      &lt;br /&gt;
    // Get an instance of the moodle file storage.                                                                                  &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
    // This is an efficient way to get a file if we know the exact path.                                                            &lt;br /&gt;
    if ($file = $fs-&amp;gt;get_file_by_hash(sha1($fullpath))) {                                                                           &lt;br /&gt;
        // We got the stored file - copy it to dataroot.                                                                            &lt;br /&gt;
        // This location matches the searched for location in theme_config::resolve_image_location.                                 &lt;br /&gt;
        $pathname = $CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039; . $settingname . &#039;.&#039; . $extension;                                 &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // This pattern matches any previous files with maybe different file extensions.                                            &lt;br /&gt;
        $pathpattern = $CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039; . $settingname . &#039;.*&#039;;                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Make sure this dir exists.                                                                                               &lt;br /&gt;
        @mkdir($CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039;, $CFG-&amp;gt;directorypermissions, true);                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Delete any existing files for this setting.                                                                              &lt;br /&gt;
        foreach (glob($pathpattern) as $filename) {                                                                                 &lt;br /&gt;
            @unlink($filename);                                                                                                     &lt;br /&gt;
        }                                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Copy the current file to this location.                                                                                  &lt;br /&gt;
        $file-&amp;gt;copy_content_to($pathname);                                                                                          &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Reset theme caches.                                                                                                          &lt;br /&gt;
    theme_reset_all_caches();                                                                                                       &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To edit the setting go to &#039;&#039;&#039;Site Administration &amp;gt; Appearance &amp;gt; Photo &amp;gt; Advanced setting&#039;&#039;&#039;. You will now see the Login page background setting.&lt;br /&gt;
It is now easy to add a new background image setting for every layout type. I can re-use this theme_photo_update_settings_images callback for each one - so all I have to do is add the setting to the settings.php file, add the SCSS rule to the scss/post.scss file and add the lang strings to the language file.&lt;br /&gt;
&lt;br /&gt;
Thats it for this tutorial, but there are [[:Category:Themes| more Themes docs]] to browse.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Themes]]&lt;/div&gt;</summary>
		<author><name>Meeth</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Creating_a_theme_based_on_boost&amp;diff=57735</id>
		<title>Creating a theme based on boost</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Creating_a_theme_based_on_boost&amp;diff=57735"/>
		<updated>2020-07-30T10:57:59Z</updated>

		<summary type="html">&lt;p&gt;Meeth: /* How do we refer to an image in SCSS ? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 3.2}}&lt;br /&gt;
{{Template:Themes}}&lt;br /&gt;
&lt;br /&gt;
This is a tutorial for how to create a new theme in any version of Moodle from 3.2 and later.&lt;br /&gt;
&lt;br /&gt;
Moodle 3.2 introduced a new core theme named &amp;quot;Boost&amp;quot; which is a great starting point for themers wanting to build a modern Moodle theme utilising all the latest features available to themes in Moodle.  If you aren&#039;t sure where to start, then START HERE!  :-)&lt;br /&gt;
&lt;br /&gt;
== Getting started ==&lt;br /&gt;
What is a theme? A theme in Moodle is just another type of plugin that can be developed. Themes are responsible for setting up the structure of each page and have the ability to customise the output of any page in Moodle.&lt;br /&gt;
&lt;br /&gt;
This tutorial is based on a working theme named &amp;quot;theme_photo&amp;quot; you can download it or view the source code for it here: https://github.com/damyon/moodle-theme_photo&lt;br /&gt;
&lt;br /&gt;
=== Choosing a name ===&lt;br /&gt;
Your new theme will need a name. Try and think of something short and memorable - and make sure it is not a name that has already been used by someone else. A quick search on the moodle.org/plugins can save you a lot of work renaming things later.&lt;br /&gt;
&lt;br /&gt;
Lets call our new example theme &amp;quot;photo&amp;quot; as we will add some settings to allow &amp;quot;photos&amp;quot; in various places in Moodle.&lt;br /&gt;
&lt;br /&gt;
=== Starting files ===&lt;br /&gt;
As a plugin, themes must start with the basic structure of a plugin in Moodle. See https://docs.moodle.org/dev/Tutorial#The_skeleton_of_your_plugin for an overview of the files common to all plugins in Moodle.&lt;br /&gt;
&lt;br /&gt;
Following this guide we can start creating our theme. First we create the folder for the new theme under &amp;quot;/theme/&amp;quot; folder in the Moodle root directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
/theme/photo/&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we need to add some standard plugin files to our theme. First is version.php&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/theme/photo/version.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the version of the plugin.                                                                                               &lt;br /&gt;
$plugin-&amp;gt;version = &#039;2016102100&#039;;                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the version of Moodle this plugin requires.                                                                              &lt;br /&gt;
$plugin-&amp;gt;requires = &#039;2016070700&#039;;                                                                                                   &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the component name of the plugin - it always starts with &#039;theme_&#039;                                                        &lt;br /&gt;
// for themes and should be the same as the name of the folder.                                                                     &lt;br /&gt;
$plugin-&amp;gt;component = &#039;theme_photo&#039;;                                                                                                 &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a list of plugins, this plugin depends on (and their versions).                                                          &lt;br /&gt;
$plugin-&amp;gt;dependencies = [                                                                                                           &lt;br /&gt;
    &#039;theme_boost&#039; =&amp;gt; &#039;2016102100&#039;                                                                                                   &lt;br /&gt;
];                                                                              &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need a language file so that all our strings can be translated into different languages. The name of this file is the component name of our plugin and it sits in the lang/en/ folder for our plugin. We can include translations of our plugin, but we can also provide translations via the https://lang.moodle.org/ website once our plugin has been published to the plugins database at http://www.moodle.org/plugins/.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/theme/photo/lang/en/theme_photo.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// A description shown in the admin theme selector.                                                                                 &lt;br /&gt;
$string[&#039;choosereadme&#039;] = &#039;Theme photo is a child theme of Boost. It adds the ability to upload background photos.&#039;;                &lt;br /&gt;
// The name of our plugin.                                                                                                          &lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Photo&#039;;                                                                                                    &lt;br /&gt;
// We need to include a lang string for each block region.                                                                          &lt;br /&gt;
$string[&#039;region-side-pre&#039;] = &#039;Right&#039;;                                         &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Theme specific files ===&lt;br /&gt;
Theme plugins have a few more standard files they need to define. &lt;br /&gt;
&lt;br /&gt;
Themes require a favicon file to show in the address bar. See [[http://docs.moodle.org/en/Favicon Favicon]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;pix/favicon.ico&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(Image file not shown).&lt;br /&gt;
&lt;br /&gt;
Themes also require an example screenshot to be displayed in the theme selector.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;pix/screenshot.jpg&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(Image file not shown).&lt;br /&gt;
&lt;br /&gt;
Themes require a lib.php file. This file contains callbacks used by various API&#039;s in Moodle. Initially this file can be empty, but as we add features to our theme we will need to add some functions here.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
// We will add callbacks here as we add features to our theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Theme config goes in a config.php file. This is one of the most important files in our theme. Once we add this file we will be ready to test our theme for the first time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
// $THEME is defined before this page is included and we can define settings by adding properties to this global object.            &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// The first setting we need is the name of the theme. This should be the last part of the component name, and the same             &lt;br /&gt;
// as the directory name for our theme.                                                                                             &lt;br /&gt;
$THEME-&amp;gt;name = &#039;photo&#039;;                                                                                                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This setting list the style sheets we want to include in our theme. Because we want to use SCSS instead of CSS - we won&#039;t        &lt;br /&gt;
// list any style sheets. If we did we would list the name of a file in the /style/ folder for our theme without any css file      &lt;br /&gt;
// extensions.                                                                                                                      &lt;br /&gt;
$THEME-&amp;gt;sheets = [];                                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a setting that can be used to provide some styling to the content in the TinyMCE text editor. This is no longer the      &lt;br /&gt;
// default text editor and &amp;quot;Atto&amp;quot; does not need this setting so we won&#039;t provide anything. If we did it would work the same         &lt;br /&gt;
// as the previous setting - listing a file in the /styles/ folder.                                                                 &lt;br /&gt;
$THEME-&amp;gt;editor_sheets = [];                                                                                                         &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a critical setting. We want to inherit from theme_boost because it provides a great starting point for SCSS bootstrap4   &lt;br /&gt;
// themes. We could add more than one parent here to inherit from multiple parents, and if we did they would be processed in        &lt;br /&gt;
// order of importance (later themes overriding earlier ones). Things we will inherit from the parent theme include                 &lt;br /&gt;
// styles and mustache templates and some (not all) settings.                                                                       &lt;br /&gt;
$THEME-&amp;gt;parents = [&#039;boost&#039;];                                                                                                        &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// A dock is a way to take blocks out of the page and put them in a persistent floating area on the side of the page. Boost         &lt;br /&gt;
// does not support a dock so we won&#039;t either - but look at bootstrapbase for an example of a theme with a dock.                    &lt;br /&gt;
$THEME-&amp;gt;enable_dock = false;                                                                                                        &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is an old setting used to load specific CSS for some YUI JS. We don&#039;t need it in Boost based themes because Boost           &lt;br /&gt;
// provides default styling for the YUI modules that we use. It is not recommended to use this setting anymore.                     &lt;br /&gt;
$THEME-&amp;gt;yuicssmodules = array();                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// Most themes will use this rendererfactory as this is the one that allows the theme to override any other renderer.               &lt;br /&gt;
$THEME-&amp;gt;rendererfactory = &#039;theme_overridden_renderer_factory&#039;;                                                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a list of blocks that are required to exist on all pages for this theme to function correctly. For example               &lt;br /&gt;
// bootstrap base requires the settings and navigation blocks because otherwise there would be no way to navigate to all the        &lt;br /&gt;
// pages in Moodle. Boost does not require these blocks because it provides other ways to navigate built into the theme.            &lt;br /&gt;
$THEME-&amp;gt;requiredblocks = &#039;&#039;;   &lt;br /&gt;
&lt;br /&gt;
// This is a feature that tells the blocks library not to use the &amp;quot;Add a block&amp;quot; block. We don&#039;t want this in boost based themes because&lt;br /&gt;
// it forces a block region into the page when editing is enabled and it takes up too much room.&lt;br /&gt;
$THEME-&amp;gt;addblockposition = BLOCK_ADDBLOCK_POSITION_FLATNAV;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ready set go! ===&lt;br /&gt;
If you have been following along - now we are at the point where we can actually install and test our new theme. Try it now by visiting the admin notifications page to install the new plugin, and then choosing the new theme from the theme selector.&lt;br /&gt;
&lt;br /&gt;
[[https://docs.moodle.org/en/Standard_themes#Theme_selector Theme selector]]&lt;br /&gt;
&lt;br /&gt;
When you choose the new theme - you will find that it looks exactly the same as Boost. At this point with our minimal configuration - we are inheriting almost everything from our parent theme including styles and templates. You will notice though that we don&#039;t inherit the settings from our parent theme. If you choose a different preset in Boost - it is not applied in this child theme.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&lt;br /&gt;
Note: make sure your config.php file contains $THEME-&amp;gt;hidefromselector = false; (or at least set to false) or else, your theme wont show up in theme selector.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What if I want the settings too? ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&lt;br /&gt;
This section is included for completeness - but it is not recommended for themes to utilise settings from their parents. To find out how to duplicate the settings from the parent theme so they operate independently skip to [[#Duplicate the settings from Boost]].&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If I want the settings from Boost to apply to my child theme as well I need to know a bit about how each of the settings in Boost is applied to make them work in my child theme.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Setting 1 - preset.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;preset&amp;quot; file is the file that is used as the main file for scss compilation. In Boost this is controlled by the theme config value:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {&lt;br /&gt;
    return theme_boost_get_main_scss_content($theme);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_boost&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this function is doing is checking for a theme setting &amp;quot;preset&amp;quot; and either fetching the file from Moodles internal file storage, or from the /preset/ folder. The function then returns the contents of this file.&lt;br /&gt;
&lt;br /&gt;
It does not automatically work for our child theme because we have no setting named &amp;quot;preset&amp;quot; in our child theme and this code is not searching the theme parents for the setting. If we wanted it to apply we could do this in our child theme:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This setting defines the main scss file for our theme to be compiled. We could set it to a static file in the scss folder or to a function which returns the SCSS based on theme settings.&lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {&lt;br /&gt;
&lt;br /&gt;
    // We need to load the config for our parent theme because that is where the preset setting is defined.&lt;br /&gt;
    $parentconfig = theme_config::load(&#039;boost&#039;);&lt;br /&gt;
    // Call a function from our parent themes lib.php file to fetch the content of the themes main SCSS file based on it&#039;s own config, not ours.&lt;br /&gt;
    return theme_boost_get_main_scss_content($parentconfig);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings 2+3 brandcolor + scsspre&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The way these settings work is they generate a chunk of SCSS to be prepended to the main scss file. In boost they work like this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;prescsscallback = &#039;theme_boost_get_pre_scss&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_pre_scss($theme) {                                                                                         &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $configurable = [                                                                                                               &lt;br /&gt;
        // Config key =&amp;gt; [variableName, ...].                                                                                       &lt;br /&gt;
        &#039;brandcolor&#039; =&amp;gt; [&#039;brand-primary&#039;],                                                                                          &lt;br /&gt;
    ];                                                                                                                              &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Prepend variables first.                                                                                                     &lt;br /&gt;
    foreach ($configurable as $configkey =&amp;gt; $targets) {                                                                             &lt;br /&gt;
        $value = isset($theme-&amp;gt;settings-&amp;gt;{$configkey}) ? $theme-&amp;gt;settings-&amp;gt;{$configkey} : null;                                     &lt;br /&gt;
        if (empty($value)) {                                                                                                        &lt;br /&gt;
            continue;                                                                                                               &lt;br /&gt;
        }                                                                                                                           &lt;br /&gt;
        array_map(function($target) use (&amp;amp;$scss, $value) {                                                                          &lt;br /&gt;
            $scss .= &#039;$&#039; . $target . &#039;: &#039; . $value . &amp;quot;;\n&amp;quot;;                                                                         &lt;br /&gt;
        }, (array) $targets);                                                                                                       &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Prepend pre-scss.                                                                                                            &lt;br /&gt;
    if (!empty($theme-&amp;gt;settings-&amp;gt;scsspre)) {                                                                                        &lt;br /&gt;
        $scss .= $theme-&amp;gt;settings-&amp;gt;scsspre;                                                                                         &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}  &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this code is doing is: &lt;br /&gt;
* looping over a list of theme settings that map to a SCSS variable and building some SCSS to initialise that variable from the setting. In Boost there is only one * brandprimary - but if we wanted to expose more bootstrap variables as theme settings we could use this function as a template in our child theme and add more settings to the $configurable array.&lt;br /&gt;
* Adding all of the raw SCSS from the scsspre theme setting&lt;br /&gt;
* Returning the whole thing as a string to be added before the main scss file.&lt;br /&gt;
&lt;br /&gt;
If we want this code to work in our child theme, using the settings from Boost we could do this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is a function that returns some SCSS as a string to prepend to the main SCSS file.                                          &lt;br /&gt;
$THEME-&amp;gt;prescsscallback = &#039;theme_photo_get_pre_scss&#039;;               &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Function to return the SCSS to prepend to our main SCSS for this theme.&lt;br /&gt;
// Note the function name starts with the component name because this is a global function and we don&#039;t want namespace clashes.&lt;br /&gt;
function theme_photo_get_pre_scss($theme) {&lt;br /&gt;
    // Load the settings from the parent.                                                                                           &lt;br /&gt;
    $theme = theme_config::load(&#039;boost&#039;);                                                                                           &lt;br /&gt;
    // Call the parent themes get_pre_scss function.                                                                                &lt;br /&gt;
    return theme_boost_get_pre_scss($theme);                         &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Setting 4 scss (post)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The final setting from Boost is a raw text field which adds SCSS to the end of the main SCSS file. This is a useful place to add style rules as they will override previously defined styles with the same specificity. It is applied in Boost by the following lines:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;extrascsscallback = &#039;theme_boost_get_extra_scss&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_extra_scss($theme) {                                                                                       &lt;br /&gt;
    return !empty($theme-&amp;gt;settings-&amp;gt;scss) ? $theme-&amp;gt;settings-&amp;gt;scss : &#039;&#039;;                                                            &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is just returning the value of the setting as a string.&lt;br /&gt;
&lt;br /&gt;
To make this setting apply in our child theme too - we use similar code to the previous sections.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is a function that returns some SCSS as a string to append to the main SCSS file.                                          &lt;br /&gt;
$THEME-&amp;gt;extrascsscallback = &#039;theme_photo_get_extra_scss&#039;;               &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Function to return the SCSS to append to our main SCSS for this theme.&lt;br /&gt;
// Note the function name starts with the component name because this is a global function and we don&#039;t want namespace clashes.&lt;br /&gt;
function theme_photo_get_extra_scss($theme) {&lt;br /&gt;
    // Load the settings from the parent.                                                                                           &lt;br /&gt;
    $theme = theme_config::load(&#039;boost&#039;);                                                                                           &lt;br /&gt;
    // Call the parent themes get_extra_scss function.                                                                                &lt;br /&gt;
    return theme_boost_get_extra_scss($theme);                         &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Duplicate the settings from Boost  ===&lt;br /&gt;
&lt;br /&gt;
This is the recommended way to extend boost as your child theme will not be affected by changes to the Boost settings, and both themes can be in use with different settings applied.&lt;br /&gt;
&lt;br /&gt;
All that needs to happen is to create theme settings in the child theme that match each of the settings in the parent theme. You will need to add matching language strings for each of these settings in the language file.&lt;br /&gt;
&lt;br /&gt;
This example shows how to do it - We are re-using the nice looking theme_boost_admin_settingspage_tabs class from boost and creating duplicate versions of each of the settings.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is used for performance, we don&#039;t need to know about these settings on every page in Moodle, only when                      &lt;br /&gt;
// we are looking at the admin settings pages.                                                                                      &lt;br /&gt;
if ($ADMIN-&amp;gt;fulltree) {                                                                                                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Boost provides a nice setting page which splits settings onto separate tabs. We want to use it here.                         &lt;br /&gt;
    $settings = new theme_boost_admin_settingspage_tabs(&#039;themesettingphoto&#039;, get_string(&#039;configtitle&#039;, &#039;theme_photo&#039;));             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Each page is a tab - the first is the &amp;quot;General&amp;quot; tab.                                                                         &lt;br /&gt;
    $page = new admin_settingpage(&#039;theme_photo_general&#039;, get_string(&#039;generalsettings&#039;, &#039;theme_photo&#039;));                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Replicate the preset setting from boost.                                                                                     &lt;br /&gt;
    $name = &#039;theme_photo/preset&#039;;                                                                                                   &lt;br /&gt;
    $title = get_string(&#039;preset&#039;, &#039;theme_photo&#039;);                                                                                   &lt;br /&gt;
    $description = get_string(&#039;preset_desc&#039;, &#039;theme_photo&#039;);                                                                        &lt;br /&gt;
    $default = &#039;default.scss&#039;;                                                                                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // We list files in our own file area to add to the drop down. We will provide our own function to                              &lt;br /&gt;
    // load all the presets from the correct paths.                                                                                 &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
    $files = $fs-&amp;gt;get_area_files($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;itemid, filepath, filename&#039;, false);                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $choices = [];                                                                                                                  &lt;br /&gt;
    foreach ($files as $file) {                                                                                                     &lt;br /&gt;
        $choices[$file-&amp;gt;get_filename()] = $file-&amp;gt;get_filename();                                                                    &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
    // These are the built in presets from Boost.                                                                                   &lt;br /&gt;
    $choices[&#039;default.scss&#039;] = &#039;default.scss&#039;;                                                                                      &lt;br /&gt;
    $choices[&#039;plain.scss&#039;] = &#039;plain.scss&#039;;                                                                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $setting = new admin_setting_configselect($name, $title, $description, $default, $choices);                                     &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Preset files setting.                                                                                                        &lt;br /&gt;
    $name = &#039;theme_photo/presetfiles&#039;;                                                                                              &lt;br /&gt;
    $title = get_string(&#039;presetfiles&#039;,&#039;theme_photo&#039;);                                                                               &lt;br /&gt;
    $description = get_string(&#039;presetfiles_desc&#039;, &#039;theme_photo&#039;);                                                                   &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;preset&#039;, 0,                                         &lt;br /&gt;
        array(&#039;maxfiles&#039; =&amp;gt; 20, &#039;accepted_types&#039; =&amp;gt; array(&#039;.scss&#039;)));                                                               &lt;br /&gt;
    $page-&amp;gt;add($setting);     &lt;br /&gt;
&lt;br /&gt;
    // Variable $brand-color.                                                                                                       &lt;br /&gt;
    // We use an empty default value because the default colour should come from the preset.                                        &lt;br /&gt;
    $name = &#039;theme_photo/brandcolor&#039;;                                                                                               &lt;br /&gt;
    $title = get_string(&#039;brandcolor&#039;, &#039;theme_photo&#039;);                                                                               &lt;br /&gt;
    $description = get_string(&#039;brandcolor_desc&#039;, &#039;theme_photo&#039;);                                                                    &lt;br /&gt;
    $setting = new admin_setting_configcolourpicker($name, $title, $description, &#039;&#039;);                                               &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Must add the page after definiting all the settings!                                                                         &lt;br /&gt;
    $settings-&amp;gt;add($page);                                                                                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Advanced settings.                                                                                                           &lt;br /&gt;
    $page = new admin_settingpage(&#039;theme_photo_advanced&#039;, get_string(&#039;advancedsettings&#039;, &#039;theme_photo&#039;));                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Raw SCSS to include before the content.                                                                                      &lt;br /&gt;
    $setting = new admin_setting_configtextarea(&#039;theme_photo/scsspre&#039;,                                                              &lt;br /&gt;
        get_string(&#039;rawscsspre&#039;, &#039;theme_photo&#039;), get_string(&#039;rawscsspre_desc&#039;, &#039;theme_photo&#039;), &#039;&#039;, PARAM_RAW);                      &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Raw SCSS to include after the content.                                                                                       &lt;br /&gt;
    $setting = new admin_setting_configtextarea(&#039;theme_photo/scss&#039;, get_string(&#039;rawscss&#039;, &#039;theme_photo&#039;),                           &lt;br /&gt;
        get_string(&#039;rawscss_desc&#039;, &#039;theme_photo&#039;), &#039;&#039;, PARAM_RAW);                                                                  &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $settings-&amp;gt;add($page);                                                                                                          &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lang/en/theme_photo.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
// The name of the second tab in the theme settings.                                                                                &lt;br /&gt;
$string[&#039;advancedsettings&#039;] = &#039;Advanced settings&#039;;                                                                                  &lt;br /&gt;
// The brand colour setting.                                                                                                        &lt;br /&gt;
$string[&#039;brandcolor&#039;] = &#039;Brand colour&#039;;                                                                                             &lt;br /&gt;
// The brand colour setting description.                                                                                            &lt;br /&gt;
$string[&#039;brandcolor_desc&#039;] = &#039;The accent colour.&#039;;     &lt;br /&gt;
// A description shown in the admin theme selector.                                                                                 &lt;br /&gt;
$string[&#039;choosereadme&#039;] = &#039;Theme photo is a child theme of Boost. It adds the ability to upload background photos.&#039;;                &lt;br /&gt;
// Name of the settings pages.                                                                                                      &lt;br /&gt;
$string[&#039;configtitle&#039;] = &#039;Photo settings&#039;;                                                                                          &lt;br /&gt;
// Name of the first settings tab.                                                                                                  &lt;br /&gt;
$string[&#039;generalsettings&#039;] = &#039;General settings&#039;;                                                                                    &lt;br /&gt;
// The name of our plugin.                                                                                                          &lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Photo&#039;;                                                                                                    &lt;br /&gt;
// Preset files setting.                                                                                                            &lt;br /&gt;
$string[&#039;presetfiles&#039;] = &#039;Additional theme preset files&#039;;                                                                           &lt;br /&gt;
// Preset files help text.                                                                                                          &lt;br /&gt;
$string[&#039;presetfiles_desc&#039;] = &#039;Preset files can be used to dramatically alter the appearance of the theme. See &amp;lt;a href=https://docs.moodle.org/dev/Boost_Presets&amp;gt;Boost presets&amp;lt;/a&amp;gt; for information on creating and sharing your own preset files, and see the &amp;lt;a href=http://moodle.net/boost&amp;gt;Presets repository&amp;lt;/a&amp;gt; for presets that others have shared.&#039;;&lt;br /&gt;
// Preset setting.                                                                                                                  &lt;br /&gt;
$string[&#039;preset&#039;] = &#039;Theme preset&#039;;                                                                                                 &lt;br /&gt;
// Preset help text.                                                                                                                &lt;br /&gt;
$string[&#039;preset_desc&#039;] = &#039;Pick a preset to broadly change the look of the theme.&#039;;                                                  &lt;br /&gt;
// Raw SCSS setting.                                                                                                                &lt;br /&gt;
$string[&#039;rawscss&#039;] = &#039;Raw SCSS&#039;;                                                                                                    &lt;br /&gt;
// Raw SCSS setting help text.                                                                                                      &lt;br /&gt;
$string[&#039;rawscss_desc&#039;] = &#039;Use this field to provide SCSS or CSS code which will be injected at the end of the style sheet.&#039;;       &lt;br /&gt;
// Raw initial SCSS setting.                                                                                                        &lt;br /&gt;
$string[&#039;rawscsspre&#039;] = &#039;Raw initial SCSS&#039;;                                                                                         &lt;br /&gt;
// Raw initial SCSS setting help text.                                                                                              &lt;br /&gt;
$string[&#039;rawscsspre_desc&#039;] = &#039;In this field you can provide initialising SCSS code, it will be injected before everything else. Most of the time you will use this setting to define variables.&#039;;&lt;br /&gt;
// We need to include a lang string for each block region.                                                                          &lt;br /&gt;
$string[&#039;region-side-pre&#039;] = &#039;Right&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We aren&#039;t quite there yet as you will notice if you try and upload a preset file and then choose it. The &amp;quot;theme_boost_get_main_scss_content&amp;quot; function from Boost is expecting the preset files to be stored in a file area for theme_boost only. We need to add this function to our own theme and tweak it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is the function that returns the SCSS source for the main file in our theme. We override the boost version because          &lt;br /&gt;
// we want to allow presets uploaded to our own theme file area to be selected in the preset list.                                  &lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {                                                                                                   &lt;br /&gt;
    return theme_photo_get_main_scss_content($theme);                                                                               &lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        // This preset file was fetched from the file area for theme_photo and not theme_boost (see the line above).                &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}             &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Stop and try it out ===&lt;br /&gt;
So now what is working and what isn&#039;t. Well - everything should be working and you should have a nice new theme extending boost with it&#039;s own settings pages. When Boost gets updates for bug fixes your new theme will inherit those fixes as it inherits all the SCSS and templates from theme boost. In addition your new theme will accept preset files and supports all the same features and settings as boost, ready to add more.&lt;br /&gt;
&lt;br /&gt;
== Take it further ==&lt;br /&gt;
Now we have our very nice starting point we can start changing or adding features, customising templates and output or tweaking the SCSS.&lt;br /&gt;
&lt;br /&gt;
=== Add some new settings ===&lt;br /&gt;
&lt;br /&gt;
From this point in the tutorial we will start adding features to our theme to extend it and make it AWESOME!&lt;br /&gt;
&lt;br /&gt;
Lets start with a new setting to set a background image on the login page. As you saw earlier, our theme defines it&#039;s list of settings in a file called settings.php. See [[Admin settings]] for more information about adding admin settings to any plugin. All of the different kinds of admin settings can be found in lib/adminlib.php. In our case we will want to add a setting which allows an admin to upload an image file. This is an &amp;quot;admin_setting_configstoredfile&amp;quot; and we add it to our theme by adding  this code to the settings.php file (inside the &amp;quot;if ($ADMIN-&amp;gt;fulltree) {&amp;quot; condition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    // Login page background setting.                                                                                               &lt;br /&gt;
    // We use variables for readability.                                                                                            &lt;br /&gt;
    $name = &#039;theme_photo/loginbackgroundimage&#039;;                                                                                     &lt;br /&gt;
    $title = get_string(&#039;loginbackgroundimage&#039;, &#039;theme_photo&#039;);                                                                     &lt;br /&gt;
    $description = get_string(&#039;loginbackgroundimage_desc&#039;, &#039;theme_photo&#039;);                                                          &lt;br /&gt;
    // This creates the new setting.                                                                                                &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;loginbackgroundimage&#039;);                             &lt;br /&gt;
    // This means that theme caches will automatically be cleared when this setting is changed.                                     &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    // We always have to add the setting to a page for it to have any effect.                                                       &lt;br /&gt;
    $page-&amp;gt;add($setting);       &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need to add new lang strings to our language file.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lang/en/theme_photo.php&amp;quot;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Background image for login page.                                                                                                 &lt;br /&gt;
$string[&#039;loginbackgroundimage&#039;] = &#039;Login page background image&#039;;                                                                    &lt;br /&gt;
// Background image for login page.                                                                                                 &lt;br /&gt;
$string[&#039;loginbackgroundimage_desc&#039;] = &#039;An image that will be stretched to fill the background of the login page.&#039;;                 &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have a new setting that lets us upload a file - but it doesn&#039;t actually do anything yet. We need to update the theme to set this image background on the login page.&lt;br /&gt;
&lt;br /&gt;
In order to change the SCSS for our theme we will add 2 additional SCSS files and include them before and after our main scss.&lt;br /&gt;
&lt;br /&gt;
We already have a function in our lib.php file which fetches the main SCSS for our theme. This is a good point to include additional SCSS files. We can add 2 lines to the end of this function to achieve this.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        // This preset file was fetched from the file area for theme_photo and not theme_boost (see the line above).                &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Pre CSS - this is loaded AFTER any prescss from the setting but before the main scss.                                        &lt;br /&gt;
    $pre = file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/photo/scss/pre.scss&#039;);                                                         &lt;br /&gt;
    // Post CSS - this is loaded AFTER the main scss but before the extra scss from the setting.                                    &lt;br /&gt;
    $post = file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/photo/scss/post.scss&#039;);                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Combine them together.                                                                                                       &lt;br /&gt;
    return $pre . &amp;quot;\n&amp;quot; . $scss . &amp;quot;\n&amp;quot; . $post;                                                                                      &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;scss/pre.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
// Pre SCSS for the theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;scss/post.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
// Post SCSS for the theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Why do we use pre and post SCSS? ====&lt;br /&gt;
SCSS/SASS is a powerful language for creating CSS. It supports variables, functions, loops just like php. For lots of information and an introduction to SCSS read about [https://en.wikipedia.org/wiki/Sass_(stylesheet_language) Sass on wikipedia]. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pre SCSS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In Boost we use many variables when creating style rules.&lt;br /&gt;
&lt;br /&gt;
When declaring a variable in SCSS - it is best practice to define it like this:&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
$mycoolcolour: #FF0 !default;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this means is - if this variable is not defined already - set it to the hex value &#039;#FF0&#039;;&lt;br /&gt;
&lt;br /&gt;
So by setting this variable in some PRE scss we can override the default value of this variable everywhere it is used. Boost is built with the [https://v4-alpha.getbootstrap.com/ Bootstrap 4 (Alpha 4)] CSS Framework. This is a framework which uses SCSS to provide many extremely useful layouts and components which can be reused without adding specific CSS rules to style every page. Because bootstrap consistently uses variables we can customise many of these components easily by setting the value of the variables before we include the Bootstrap SCSS files.&lt;br /&gt;
&lt;br /&gt;
Many variables are available in /theme/boost/scss/bootstrap/_variables.scss - as an example we can change the look of all buttons and input fields with this one variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
$border-radius: 8px;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Post SCSS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Post SCSS is useful for defining full CSS rules. Because they are included last, they override any previous matching selector with the same [https://en.wikipedia.org/wiki/Cascading_Style_Sheets#Specificity Specificity].&lt;br /&gt;
&lt;br /&gt;
=== Tips for customising Moodle with SCSS (or CSS) ===&lt;br /&gt;
Some handy things to know when you are new to theming is that Moodle adds some classes to every page that helps you target a specific page or set of pages with some style rules. &lt;br /&gt;
&lt;br /&gt;
If you inspect a moodle page and look at the body tag you will see a long list of classes e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code html&amp;gt;&lt;br /&gt;
&amp;lt;body id=&amp;quot;page-course-view-weeks&amp;quot; class=&amp;quot;format-weeks  path-course path-course-view safari dir-ltr lang-en yui-skin-sam yui3-skin-sam damyon-per-in-moodle-com--stable_master pagelayout-course course-11 context-497 category-1 drawer-open-left jsenabled&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can see from this example that each page gets an id. This is a simplified representation of the current page in the navigation. In this example we are looking at the course page and this course is using the weeks format. &lt;br /&gt;
&lt;br /&gt;
The classes on the body tag can also be used to target a page or set of pages.&lt;br /&gt;
* &amp;lt;code&amp;gt;format-weeks&amp;lt;/code&amp;gt; The course format&lt;br /&gt;
* &amp;lt;code&amp;gt;path-course path-course-view&amp;lt;/code&amp;gt; The parts of the bread-crumb leading up to the current page (The current page is what goes in the id)&lt;br /&gt;
* &amp;lt;code&amp;gt;safari&amp;lt;/code&amp;gt; Some server side guessing of the browser type - it&#039;s not accurate so I would not rely on it&lt;br /&gt;
* &amp;lt;code&amp;gt;dir-ltr&amp;lt;/code&amp;gt; The direction of the current language for the page ( dir-rtl for RTL languages )&lt;br /&gt;
* &amp;lt;code&amp;gt;lang-en&amp;lt;/code&amp;gt; The current language of the page&lt;br /&gt;
* &amp;lt;code&amp;gt;yui*&amp;lt;/code&amp;gt; Legacy yui classes - ignore these&lt;br /&gt;
* &amp;lt;code&amp;gt;damyon-per-in-moodle-com--stable_master&amp;lt;/code&amp;gt; The current hostname for the site + the site name&lt;br /&gt;
* &amp;lt;code&amp;gt;pagelayout-course&amp;lt;/code&amp;gt; The layout type for the current page&lt;br /&gt;
* &amp;lt;code&amp;gt;course-11&amp;lt;/code&amp;gt; The id of the current course&lt;br /&gt;
* &amp;lt;code&amp;gt;context-497&amp;lt;/code&amp;gt; The current context id&lt;br /&gt;
* &amp;lt;code&amp;gt;category-1&amp;lt;/code&amp;gt; The category for the current course&lt;br /&gt;
* &amp;lt;code&amp;gt;drawer-open-left&amp;lt;/code&amp;gt; Added / removed when the navigation drawer is opened / closed in Boost&lt;br /&gt;
* &amp;lt;code&amp;gt;jsenabled&amp;lt;/code&amp;gt; True if the browser supports javascript&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/dev/Themes_overview#.3Cbody.3E_CSS_id_and_classes Read about Body id and classes].&lt;br /&gt;
&lt;br /&gt;
In our example the page layout is the most useful here as we have a specific page layout for login pages. We can now craft a rule that applies a background image only to login pages using &amp;quot;body.pagelayout-login&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How do we refer to an image in SCSS ? ===&lt;br /&gt;
So now we can add a rule to the post.scss which will set the background image for the login page. First we need to know how to construct a url to the background images from our stylesheet. &lt;br /&gt;
&lt;br /&gt;
In stylesheets in Moodle we can use a special pix tag to refer to images from our theme. The rule to attach the background image looks like this:&lt;br /&gt;
&#039;&#039;scss/post.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
body.pagelayout-login {                                                                                                             &lt;br /&gt;
    background-image: url([[pix:theme_photo|loginbackgroundimage]]);                                                                &lt;br /&gt;
    background-size: cover;                                                                                                         &lt;br /&gt;
}                          &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are 2 important parts to this tag (the bit in square brackets). The first is &amp;quot;theme_photo&amp;quot;. In this case we are passing a component name, the image serving code in theme_config::resolve_image_location() will then look for an image file in several locations. One of these is in &amp;quot;$CFG-&amp;gt;dataroot/pix_plugins/$type/$plugin/$image&amp;quot;. We can use this to make sure the image gets served correctly by copying the file saved in the setting to this location every time it is updated. (There is an alterative way we could do this by implementing pluginfile.php in our theme - which you can read about in the [[File API]] ).&lt;br /&gt;
&lt;br /&gt;
If we had just passed the value &amp;quot;theme&amp;quot; the image serving code would have looked for the image in the &amp;quot;pix&amp;quot; folder of our theme.&lt;br /&gt;
&lt;br /&gt;
So - we need this final change to copy the image file into our dataroot each time the setting is changed.&lt;br /&gt;
&lt;br /&gt;
In the settings file we will update the callback to a new function which we will define in our lib.php.&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Login page background setting.                                                                                               &lt;br /&gt;
    // We use variables for readability.                                                                                            &lt;br /&gt;
    $name = &#039;theme_photo/loginbackgroundimage&#039;;                                                                                     &lt;br /&gt;
    $title = get_string(&#039;loginbackgroundimage&#039;, &#039;theme_photo&#039;);                                                                     &lt;br /&gt;
    $description = get_string(&#039;loginbackgroundimage_desc&#039;, &#039;theme_photo&#039;);                                                          &lt;br /&gt;
    // This creates the new setting.                                                                                                &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;loginbackgroundimage&#039;);                             &lt;br /&gt;
    // This function will copy the image into the data_root location it can be served from.                                         &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_photo_update_settings_images&#039;);                                                            &lt;br /&gt;
    // We always have to add the setting to a page for it to have any effect.                                                       &lt;br /&gt;
    $page-&amp;gt;add($setting);&lt;br /&gt;
    //This will commit the background image setting. If you do not add this line the Login page background setting will not be shown.&lt;br /&gt;
    $settings-&amp;gt;add($page);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_update_settings_images($settingname) {                                                                         &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // The setting name that was updated comes as a string like &#039;s_theme_photo_loginbackgroundimage&#039;.                               &lt;br /&gt;
    // We split it on &#039;_&#039; characters.                                                                                               &lt;br /&gt;
    $parts = explode(&#039;_&#039;, $settingname);                                                                                            &lt;br /&gt;
    // And get the last one to get the setting name..                                                                               &lt;br /&gt;
    $settingname = end($parts);                                                                                                     &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Admin settings are stored in system context.                                                                                 &lt;br /&gt;
    $syscontext = context_system::instance();                                                                                       &lt;br /&gt;
    // This is the component name the setting is stored in.                                                                         &lt;br /&gt;
    $component = &#039;theme_photo&#039;;                                                                                                     &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // This is the value of the admin setting which is the filename of the uploaded file.                                           &lt;br /&gt;
    $filename = get_config($component, $settingname);                                                                               &lt;br /&gt;
    // We extract the file extension because we want to preserve it.                                                                &lt;br /&gt;
    $extension = substr($filename, strrpos($filename, &#039;.&#039;) + 1);                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // This is the path in the moodle internal file system.                                                                         &lt;br /&gt;
    $fullpath = &amp;quot;/{$syscontext-&amp;gt;id}/{$component}/{$settingname}/0{$filename}&amp;quot;;                                                      &lt;br /&gt;
    // Get an instance of the moodle file storage.                                                                                  &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
    // This is an efficient way to get a file if we know the exact path.                                                            &lt;br /&gt;
    if ($file = $fs-&amp;gt;get_file_by_hash(sha1($fullpath))) {                                                                           &lt;br /&gt;
        // We got the stored file - copy it to dataroot.                                                                            &lt;br /&gt;
        // This location matches the searched for location in theme_config::resolve_image_location.                                 &lt;br /&gt;
        $pathname = $CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039; . $settingname . &#039;.&#039; . $extension;                                 &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // This pattern matches any previous files with maybe different file extensions.                                            &lt;br /&gt;
        $pathpattern = $CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039; . $settingname . &#039;.*&#039;;                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Make sure this dir exists.                                                                                               &lt;br /&gt;
        @mkdir($CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039;, $CFG-&amp;gt;directorypermissions, true);                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Delete any existing files for this setting.                                                                              &lt;br /&gt;
        foreach (glob($pathpattern) as $filename) {                                                                                 &lt;br /&gt;
            @unlink($filename);                                                                                                     &lt;br /&gt;
        }                                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Copy the current file to this location.                                                                                  &lt;br /&gt;
        $file-&amp;gt;copy_content_to($pathname);                                                                                          &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Reset theme caches.                                                                                                          &lt;br /&gt;
    theme_reset_all_caches();                                                                                                       &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To edit the setting go to &#039;&#039;&#039;Site Administration &amp;gt; Appearance &amp;gt; Photo &amp;gt; Advanced setting&#039;&#039;&#039;. You will now see the Login page background setting.&lt;br /&gt;
It is now easy to add a new background image setting for every layout type. I can re-use this theme_photo_update_settings_images callback for each one - so all I have to do is add the setting to the settings.php file, add the SCSS rule to the scss/post.scss file and add the lang strings to the language file.&lt;br /&gt;
&lt;br /&gt;
Thats it for this tutorial, but there are [[:Category:Themes| more Themes docs]] to browse.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Themes]]&lt;/div&gt;</summary>
		<author><name>Meeth</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Creating_a_theme_based_on_boost&amp;diff=57734</id>
		<title>Creating a theme based on boost</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Creating_a_theme_based_on_boost&amp;diff=57734"/>
		<updated>2020-07-29T13:40:52Z</updated>

		<summary type="html">&lt;p&gt;Meeth: Undo revision 57724 by Meeth (talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 3.2}}&lt;br /&gt;
{{Template:Themes}}&lt;br /&gt;
&lt;br /&gt;
This is a tutorial for how to create a new theme in any version of Moodle from 3.2 and later.&lt;br /&gt;
&lt;br /&gt;
Moodle 3.2 introduced a new core theme named &amp;quot;Boost&amp;quot; which is a great starting point for themers wanting to build a modern Moodle theme utilising all the latest features available to themes in Moodle.  If you aren&#039;t sure where to start, then START HERE!  :-)&lt;br /&gt;
&lt;br /&gt;
== Getting started ==&lt;br /&gt;
What is a theme? A theme in Moodle is just another type of plugin that can be developed. Themes are responsible for setting up the structure of each page and have the ability to customise the output of any page in Moodle.&lt;br /&gt;
&lt;br /&gt;
This tutorial is based on a working theme named &amp;quot;theme_photo&amp;quot; you can download it or view the source code for it here: https://github.com/damyon/moodle-theme_photo&lt;br /&gt;
&lt;br /&gt;
=== Choosing a name ===&lt;br /&gt;
Your new theme will need a name. Try and think of something short and memorable - and make sure it is not a name that has already been used by someone else. A quick search on the moodle.org/plugins can save you a lot of work renaming things later.&lt;br /&gt;
&lt;br /&gt;
Lets call our new example theme &amp;quot;photo&amp;quot; as we will add some settings to allow &amp;quot;photos&amp;quot; in various places in Moodle.&lt;br /&gt;
&lt;br /&gt;
=== Starting files ===&lt;br /&gt;
As a plugin, themes must start with the basic structure of a plugin in Moodle. See https://docs.moodle.org/dev/Tutorial#The_skeleton_of_your_plugin for an overview of the files common to all plugins in Moodle.&lt;br /&gt;
&lt;br /&gt;
Following this guide we can start creating our theme. First we create the folder for the new theme under &amp;quot;/theme/&amp;quot; folder in the Moodle root directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
/theme/photo/&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we need to add some standard plugin files to our theme. First is version.php&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/theme/photo/version.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the version of the plugin.                                                                                               &lt;br /&gt;
$plugin-&amp;gt;version = &#039;2016102100&#039;;                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the version of Moodle this plugin requires.                                                                              &lt;br /&gt;
$plugin-&amp;gt;requires = &#039;2016070700&#039;;                                                                                                   &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the component name of the plugin - it always starts with &#039;theme_&#039;                                                        &lt;br /&gt;
// for themes and should be the same as the name of the folder.                                                                     &lt;br /&gt;
$plugin-&amp;gt;component = &#039;theme_photo&#039;;                                                                                                 &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a list of plugins, this plugin depends on (and their versions).                                                          &lt;br /&gt;
$plugin-&amp;gt;dependencies = [                                                                                                           &lt;br /&gt;
    &#039;theme_boost&#039; =&amp;gt; &#039;2016102100&#039;                                                                                                   &lt;br /&gt;
];                                                                              &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need a language file so that all our strings can be translated into different languages. The name of this file is the component name of our plugin and it sits in the lang/en/ folder for our plugin. We can include translations of our plugin, but we can also provide translations via the https://lang.moodle.org/ website once our plugin has been published to the plugins database at http://www.moodle.org/plugins/.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/theme/photo/lang/en/theme_photo.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// A description shown in the admin theme selector.                                                                                 &lt;br /&gt;
$string[&#039;choosereadme&#039;] = &#039;Theme photo is a child theme of Boost. It adds the ability to upload background photos.&#039;;                &lt;br /&gt;
// The name of our plugin.                                                                                                          &lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Photo&#039;;                                                                                                    &lt;br /&gt;
// We need to include a lang string for each block region.                                                                          &lt;br /&gt;
$string[&#039;region-side-pre&#039;] = &#039;Right&#039;;                                         &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Theme specific files ===&lt;br /&gt;
Theme plugins have a few more standard files they need to define. &lt;br /&gt;
&lt;br /&gt;
Themes require a favicon file to show in the address bar. See [[http://docs.moodle.org/en/Favicon Favicon]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;pix/favicon.ico&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(Image file not shown).&lt;br /&gt;
&lt;br /&gt;
Themes also require an example screenshot to be displayed in the theme selector.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;pix/screenshot.jpg&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(Image file not shown).&lt;br /&gt;
&lt;br /&gt;
Themes require a lib.php file. This file contains callbacks used by various API&#039;s in Moodle. Initially this file can be empty, but as we add features to our theme we will need to add some functions here.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
// We will add callbacks here as we add features to our theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Theme config goes in a config.php file. This is one of the most important files in our theme. Once we add this file we will be ready to test our theme for the first time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
// $THEME is defined before this page is included and we can define settings by adding properties to this global object.            &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// The first setting we need is the name of the theme. This should be the last part of the component name, and the same             &lt;br /&gt;
// as the directory name for our theme.                                                                                             &lt;br /&gt;
$THEME-&amp;gt;name = &#039;photo&#039;;                                                                                                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This setting list the style sheets we want to include in our theme. Because we want to use SCSS instead of CSS - we won&#039;t        &lt;br /&gt;
// list any style sheets. If we did we would list the name of a file in the /style/ folder for our theme without any css file      &lt;br /&gt;
// extensions.                                                                                                                      &lt;br /&gt;
$THEME-&amp;gt;sheets = [];                                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a setting that can be used to provide some styling to the content in the TinyMCE text editor. This is no longer the      &lt;br /&gt;
// default text editor and &amp;quot;Atto&amp;quot; does not need this setting so we won&#039;t provide anything. If we did it would work the same         &lt;br /&gt;
// as the previous setting - listing a file in the /styles/ folder.                                                                 &lt;br /&gt;
$THEME-&amp;gt;editor_sheets = [];                                                                                                         &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a critical setting. We want to inherit from theme_boost because it provides a great starting point for SCSS bootstrap4   &lt;br /&gt;
// themes. We could add more than one parent here to inherit from multiple parents, and if we did they would be processed in        &lt;br /&gt;
// order of importance (later themes overriding earlier ones). Things we will inherit from the parent theme include                 &lt;br /&gt;
// styles and mustache templates and some (not all) settings.                                                                       &lt;br /&gt;
$THEME-&amp;gt;parents = [&#039;boost&#039;];                                                                                                        &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// A dock is a way to take blocks out of the page and put them in a persistent floating area on the side of the page. Boost         &lt;br /&gt;
// does not support a dock so we won&#039;t either - but look at bootstrapbase for an example of a theme with a dock.                    &lt;br /&gt;
$THEME-&amp;gt;enable_dock = false;                                                                                                        &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is an old setting used to load specific CSS for some YUI JS. We don&#039;t need it in Boost based themes because Boost           &lt;br /&gt;
// provides default styling for the YUI modules that we use. It is not recommended to use this setting anymore.                     &lt;br /&gt;
$THEME-&amp;gt;yuicssmodules = array();                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// Most themes will use this rendererfactory as this is the one that allows the theme to override any other renderer.               &lt;br /&gt;
$THEME-&amp;gt;rendererfactory = &#039;theme_overridden_renderer_factory&#039;;                                                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a list of blocks that are required to exist on all pages for this theme to function correctly. For example               &lt;br /&gt;
// bootstrap base requires the settings and navigation blocks because otherwise there would be no way to navigate to all the        &lt;br /&gt;
// pages in Moodle. Boost does not require these blocks because it provides other ways to navigate built into the theme.            &lt;br /&gt;
$THEME-&amp;gt;requiredblocks = &#039;&#039;;   &lt;br /&gt;
&lt;br /&gt;
// This is a feature that tells the blocks library not to use the &amp;quot;Add a block&amp;quot; block. We don&#039;t want this in boost based themes because&lt;br /&gt;
// it forces a block region into the page when editing is enabled and it takes up too much room.&lt;br /&gt;
$THEME-&amp;gt;addblockposition = BLOCK_ADDBLOCK_POSITION_FLATNAV;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ready set go! ===&lt;br /&gt;
If you have been following along - now we are at the point where we can actually install and test our new theme. Try it now by visiting the admin notifications page to install the new plugin, and then choosing the new theme from the theme selector.&lt;br /&gt;
&lt;br /&gt;
[[https://docs.moodle.org/en/Standard_themes#Theme_selector Theme selector]]&lt;br /&gt;
&lt;br /&gt;
When you choose the new theme - you will find that it looks exactly the same as Boost. At this point with our minimal configuration - we are inheriting almost everything from our parent theme including styles and templates. You will notice though that we don&#039;t inherit the settings from our parent theme. If you choose a different preset in Boost - it is not applied in this child theme.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&lt;br /&gt;
Note: make sure your config.php file contains $THEME-&amp;gt;hidefromselector = false; (or at least set to false) or else, your theme wont show up in theme selector.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What if I want the settings too? ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&lt;br /&gt;
This section is included for completeness - but it is not recommended for themes to utilise settings from their parents. To find out how to duplicate the settings from the parent theme so they operate independently skip to [[#Duplicate the settings from Boost]].&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If I want the settings from Boost to apply to my child theme as well I need to know a bit about how each of the settings in Boost is applied to make them work in my child theme.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Setting 1 - preset.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;preset&amp;quot; file is the file that is used as the main file for scss compilation. In Boost this is controlled by the theme config value:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {&lt;br /&gt;
    return theme_boost_get_main_scss_content($theme);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_boost&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this function is doing is checking for a theme setting &amp;quot;preset&amp;quot; and either fetching the file from Moodles internal file storage, or from the /preset/ folder. The function then returns the contents of this file.&lt;br /&gt;
&lt;br /&gt;
It does not automatically work for our child theme because we have no setting named &amp;quot;preset&amp;quot; in our child theme and this code is not searching the theme parents for the setting. If we wanted it to apply we could do this in our child theme:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This setting defines the main scss file for our theme to be compiled. We could set it to a static file in the scss folder or to a function which returns the SCSS based on theme settings.&lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {&lt;br /&gt;
&lt;br /&gt;
    // We need to load the config for our parent theme because that is where the preset setting is defined.&lt;br /&gt;
    $parentconfig = theme_config::load(&#039;boost&#039;);&lt;br /&gt;
    // Call a function from our parent themes lib.php file to fetch the content of the themes main SCSS file based on it&#039;s own config, not ours.&lt;br /&gt;
    return theme_boost_get_main_scss_content($parentconfig);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings 2+3 brandcolor + scsspre&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The way these settings work is they generate a chunk of SCSS to be prepended to the main scss file. In boost they work like this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;prescsscallback = &#039;theme_boost_get_pre_scss&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_pre_scss($theme) {                                                                                         &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $configurable = [                                                                                                               &lt;br /&gt;
        // Config key =&amp;gt; [variableName, ...].                                                                                       &lt;br /&gt;
        &#039;brandcolor&#039; =&amp;gt; [&#039;brand-primary&#039;],                                                                                          &lt;br /&gt;
    ];                                                                                                                              &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Prepend variables first.                                                                                                     &lt;br /&gt;
    foreach ($configurable as $configkey =&amp;gt; $targets) {                                                                             &lt;br /&gt;
        $value = isset($theme-&amp;gt;settings-&amp;gt;{$configkey}) ? $theme-&amp;gt;settings-&amp;gt;{$configkey} : null;                                     &lt;br /&gt;
        if (empty($value)) {                                                                                                        &lt;br /&gt;
            continue;                                                                                                               &lt;br /&gt;
        }                                                                                                                           &lt;br /&gt;
        array_map(function($target) use (&amp;amp;$scss, $value) {                                                                          &lt;br /&gt;
            $scss .= &#039;$&#039; . $target . &#039;: &#039; . $value . &amp;quot;;\n&amp;quot;;                                                                         &lt;br /&gt;
        }, (array) $targets);                                                                                                       &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Prepend pre-scss.                                                                                                            &lt;br /&gt;
    if (!empty($theme-&amp;gt;settings-&amp;gt;scsspre)) {                                                                                        &lt;br /&gt;
        $scss .= $theme-&amp;gt;settings-&amp;gt;scsspre;                                                                                         &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}  &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this code is doing is: &lt;br /&gt;
* looping over a list of theme settings that map to a SCSS variable and building some SCSS to initialise that variable from the setting. In Boost there is only one * brandprimary - but if we wanted to expose more bootstrap variables as theme settings we could use this function as a template in our child theme and add more settings to the $configurable array.&lt;br /&gt;
* Adding all of the raw SCSS from the scsspre theme setting&lt;br /&gt;
* Returning the whole thing as a string to be added before the main scss file.&lt;br /&gt;
&lt;br /&gt;
If we want this code to work in our child theme, using the settings from Boost we could do this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is a function that returns some SCSS as a string to prepend to the main SCSS file.                                          &lt;br /&gt;
$THEME-&amp;gt;prescsscallback = &#039;theme_photo_get_pre_scss&#039;;               &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Function to return the SCSS to prepend to our main SCSS for this theme.&lt;br /&gt;
// Note the function name starts with the component name because this is a global function and we don&#039;t want namespace clashes.&lt;br /&gt;
function theme_photo_get_pre_scss($theme) {&lt;br /&gt;
    // Load the settings from the parent.                                                                                           &lt;br /&gt;
    $theme = theme_config::load(&#039;boost&#039;);                                                                                           &lt;br /&gt;
    // Call the parent themes get_pre_scss function.                                                                                &lt;br /&gt;
    return theme_boost_get_pre_scss($theme);                         &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Setting 4 scss (post)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The final setting from Boost is a raw text field which adds SCSS to the end of the main SCSS file. This is a useful place to add style rules as they will override previously defined styles with the same specificity. It is applied in Boost by the following lines:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;extrascsscallback = &#039;theme_boost_get_extra_scss&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_extra_scss($theme) {                                                                                       &lt;br /&gt;
    return !empty($theme-&amp;gt;settings-&amp;gt;scss) ? $theme-&amp;gt;settings-&amp;gt;scss : &#039;&#039;;                                                            &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is just returning the value of the setting as a string.&lt;br /&gt;
&lt;br /&gt;
To make this setting apply in our child theme too - we use similar code to the previous sections.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is a function that returns some SCSS as a string to append to the main SCSS file.                                          &lt;br /&gt;
$THEME-&amp;gt;extrascsscallback = &#039;theme_photo_get_extra_scss&#039;;               &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Function to return the SCSS to append to our main SCSS for this theme.&lt;br /&gt;
// Note the function name starts with the component name because this is a global function and we don&#039;t want namespace clashes.&lt;br /&gt;
function theme_photo_get_extra_scss($theme) {&lt;br /&gt;
    // Load the settings from the parent.                                                                                           &lt;br /&gt;
    $theme = theme_config::load(&#039;boost&#039;);                                                                                           &lt;br /&gt;
    // Call the parent themes get_extra_scss function.                                                                                &lt;br /&gt;
    return theme_boost_get_extra_scss($theme);                         &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Duplicate the settings from Boost  ===&lt;br /&gt;
&lt;br /&gt;
This is the recommended way to extend boost as your child theme will not be affected by changes to the Boost settings, and both themes can be in use with different settings applied.&lt;br /&gt;
&lt;br /&gt;
All that needs to happen is to create theme settings in the child theme that match each of the settings in the parent theme. You will need to add matching language strings for each of these settings in the language file.&lt;br /&gt;
&lt;br /&gt;
This example shows how to do it - We are re-using the nice looking theme_boost_admin_settingspage_tabs class from boost and creating duplicate versions of each of the settings.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is used for performance, we don&#039;t need to know about these settings on every page in Moodle, only when                      &lt;br /&gt;
// we are looking at the admin settings pages.                                                                                      &lt;br /&gt;
if ($ADMIN-&amp;gt;fulltree) {                                                                                                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Boost provides a nice setting page which splits settings onto separate tabs. We want to use it here.                         &lt;br /&gt;
    $settings = new theme_boost_admin_settingspage_tabs(&#039;themesettingphoto&#039;, get_string(&#039;configtitle&#039;, &#039;theme_photo&#039;));             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Each page is a tab - the first is the &amp;quot;General&amp;quot; tab.                                                                         &lt;br /&gt;
    $page = new admin_settingpage(&#039;theme_photo_general&#039;, get_string(&#039;generalsettings&#039;, &#039;theme_photo&#039;));                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Replicate the preset setting from boost.                                                                                     &lt;br /&gt;
    $name = &#039;theme_photo/preset&#039;;                                                                                                   &lt;br /&gt;
    $title = get_string(&#039;preset&#039;, &#039;theme_photo&#039;);                                                                                   &lt;br /&gt;
    $description = get_string(&#039;preset_desc&#039;, &#039;theme_photo&#039;);                                                                        &lt;br /&gt;
    $default = &#039;default.scss&#039;;                                                                                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // We list files in our own file area to add to the drop down. We will provide our own function to                              &lt;br /&gt;
    // load all the presets from the correct paths.                                                                                 &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
    $files = $fs-&amp;gt;get_area_files($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;itemid, filepath, filename&#039;, false);                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $choices = [];                                                                                                                  &lt;br /&gt;
    foreach ($files as $file) {                                                                                                     &lt;br /&gt;
        $choices[$file-&amp;gt;get_filename()] = $file-&amp;gt;get_filename();                                                                    &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
    // These are the built in presets from Boost.                                                                                   &lt;br /&gt;
    $choices[&#039;default.scss&#039;] = &#039;default.scss&#039;;                                                                                      &lt;br /&gt;
    $choices[&#039;plain.scss&#039;] = &#039;plain.scss&#039;;                                                                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $setting = new admin_setting_configselect($name, $title, $description, $default, $choices);                                     &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Preset files setting.                                                                                                        &lt;br /&gt;
    $name = &#039;theme_photo/presetfiles&#039;;                                                                                              &lt;br /&gt;
    $title = get_string(&#039;presetfiles&#039;,&#039;theme_photo&#039;);                                                                               &lt;br /&gt;
    $description = get_string(&#039;presetfiles_desc&#039;, &#039;theme_photo&#039;);                                                                   &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;preset&#039;, 0,                                         &lt;br /&gt;
        array(&#039;maxfiles&#039; =&amp;gt; 20, &#039;accepted_types&#039; =&amp;gt; array(&#039;.scss&#039;)));                                                               &lt;br /&gt;
    $page-&amp;gt;add($setting);     &lt;br /&gt;
&lt;br /&gt;
    // Variable $brand-color.                                                                                                       &lt;br /&gt;
    // We use an empty default value because the default colour should come from the preset.                                        &lt;br /&gt;
    $name = &#039;theme_photo/brandcolor&#039;;                                                                                               &lt;br /&gt;
    $title = get_string(&#039;brandcolor&#039;, &#039;theme_photo&#039;);                                                                               &lt;br /&gt;
    $description = get_string(&#039;brandcolor_desc&#039;, &#039;theme_photo&#039;);                                                                    &lt;br /&gt;
    $setting = new admin_setting_configcolourpicker($name, $title, $description, &#039;&#039;);                                               &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Must add the page after definiting all the settings!                                                                         &lt;br /&gt;
    $settings-&amp;gt;add($page);                                                                                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Advanced settings.                                                                                                           &lt;br /&gt;
    $page = new admin_settingpage(&#039;theme_photo_advanced&#039;, get_string(&#039;advancedsettings&#039;, &#039;theme_photo&#039;));                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Raw SCSS to include before the content.                                                                                      &lt;br /&gt;
    $setting = new admin_setting_configtextarea(&#039;theme_photo/scsspre&#039;,                                                              &lt;br /&gt;
        get_string(&#039;rawscsspre&#039;, &#039;theme_photo&#039;), get_string(&#039;rawscsspre_desc&#039;, &#039;theme_photo&#039;), &#039;&#039;, PARAM_RAW);                      &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Raw SCSS to include after the content.                                                                                       &lt;br /&gt;
    $setting = new admin_setting_configtextarea(&#039;theme_photo/scss&#039;, get_string(&#039;rawscss&#039;, &#039;theme_photo&#039;),                           &lt;br /&gt;
        get_string(&#039;rawscss_desc&#039;, &#039;theme_photo&#039;), &#039;&#039;, PARAM_RAW);                                                                  &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $settings-&amp;gt;add($page);                                                                                                          &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lang/en/theme_photo.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
// The name of the second tab in the theme settings.                                                                                &lt;br /&gt;
$string[&#039;advancedsettings&#039;] = &#039;Advanced settings&#039;;                                                                                  &lt;br /&gt;
// The brand colour setting.                                                                                                        &lt;br /&gt;
$string[&#039;brandcolor&#039;] = &#039;Brand colour&#039;;                                                                                             &lt;br /&gt;
// The brand colour setting description.                                                                                            &lt;br /&gt;
$string[&#039;brandcolor_desc&#039;] = &#039;The accent colour.&#039;;     &lt;br /&gt;
// A description shown in the admin theme selector.                                                                                 &lt;br /&gt;
$string[&#039;choosereadme&#039;] = &#039;Theme photo is a child theme of Boost. It adds the ability to upload background photos.&#039;;                &lt;br /&gt;
// Name of the settings pages.                                                                                                      &lt;br /&gt;
$string[&#039;configtitle&#039;] = &#039;Photo settings&#039;;                                                                                          &lt;br /&gt;
// Name of the first settings tab.                                                                                                  &lt;br /&gt;
$string[&#039;generalsettings&#039;] = &#039;General settings&#039;;                                                                                    &lt;br /&gt;
// The name of our plugin.                                                                                                          &lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Photo&#039;;                                                                                                    &lt;br /&gt;
// Preset files setting.                                                                                                            &lt;br /&gt;
$string[&#039;presetfiles&#039;] = &#039;Additional theme preset files&#039;;                                                                           &lt;br /&gt;
// Preset files help text.                                                                                                          &lt;br /&gt;
$string[&#039;presetfiles_desc&#039;] = &#039;Preset files can be used to dramatically alter the appearance of the theme. See &amp;lt;a href=https://docs.moodle.org/dev/Boost_Presets&amp;gt;Boost presets&amp;lt;/a&amp;gt; for information on creating and sharing your own preset files, and see the &amp;lt;a href=http://moodle.net/boost&amp;gt;Presets repository&amp;lt;/a&amp;gt; for presets that others have shared.&#039;;&lt;br /&gt;
// Preset setting.                                                                                                                  &lt;br /&gt;
$string[&#039;preset&#039;] = &#039;Theme preset&#039;;                                                                                                 &lt;br /&gt;
// Preset help text.                                                                                                                &lt;br /&gt;
$string[&#039;preset_desc&#039;] = &#039;Pick a preset to broadly change the look of the theme.&#039;;                                                  &lt;br /&gt;
// Raw SCSS setting.                                                                                                                &lt;br /&gt;
$string[&#039;rawscss&#039;] = &#039;Raw SCSS&#039;;                                                                                                    &lt;br /&gt;
// Raw SCSS setting help text.                                                                                                      &lt;br /&gt;
$string[&#039;rawscss_desc&#039;] = &#039;Use this field to provide SCSS or CSS code which will be injected at the end of the style sheet.&#039;;       &lt;br /&gt;
// Raw initial SCSS setting.                                                                                                        &lt;br /&gt;
$string[&#039;rawscsspre&#039;] = &#039;Raw initial SCSS&#039;;                                                                                         &lt;br /&gt;
// Raw initial SCSS setting help text.                                                                                              &lt;br /&gt;
$string[&#039;rawscsspre_desc&#039;] = &#039;In this field you can provide initialising SCSS code, it will be injected before everything else. Most of the time you will use this setting to define variables.&#039;;&lt;br /&gt;
// We need to include a lang string for each block region.                                                                          &lt;br /&gt;
$string[&#039;region-side-pre&#039;] = &#039;Right&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We aren&#039;t quite there yet as you will notice if you try and upload a preset file and then choose it. The &amp;quot;theme_boost_get_main_scss_content&amp;quot; function from Boost is expecting the preset files to be stored in a file area for theme_boost only. We need to add this function to our own theme and tweak it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is the function that returns the SCSS source for the main file in our theme. We override the boost version because          &lt;br /&gt;
// we want to allow presets uploaded to our own theme file area to be selected in the preset list.                                  &lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {                                                                                                   &lt;br /&gt;
    return theme_photo_get_main_scss_content($theme);                                                                               &lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        // This preset file was fetched from the file area for theme_photo and not theme_boost (see the line above).                &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}             &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Stop and try it out ===&lt;br /&gt;
So now what is working and what isn&#039;t. Well - everything should be working and you should have a nice new theme extending boost with it&#039;s own settings pages. When Boost gets updates for bug fixes your new theme will inherit those fixes as it inherits all the SCSS and templates from theme boost. In addition your new theme will accept preset files and supports all the same features and settings as boost, ready to add more.&lt;br /&gt;
&lt;br /&gt;
== Take it further ==&lt;br /&gt;
Now we have our very nice starting point we can start changing or adding features, customising templates and output or tweaking the SCSS.&lt;br /&gt;
&lt;br /&gt;
=== Add some new settings ===&lt;br /&gt;
&lt;br /&gt;
From this point in the tutorial we will start adding features to our theme to extend it and make it AWESOME!&lt;br /&gt;
&lt;br /&gt;
Lets start with a new setting to set a background image on the login page. As you saw earlier, our theme defines it&#039;s list of settings in a file called settings.php. See [[Admin settings]] for more information about adding admin settings to any plugin. All of the different kinds of admin settings can be found in lib/adminlib.php. In our case we will want to add a setting which allows an admin to upload an image file. This is an &amp;quot;admin_setting_configstoredfile&amp;quot; and we add it to our theme by adding  this code to the settings.php file (inside the &amp;quot;if ($ADMIN-&amp;gt;fulltree) {&amp;quot; condition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    // Login page background setting.                                                                                               &lt;br /&gt;
    // We use variables for readability.                                                                                            &lt;br /&gt;
    $name = &#039;theme_photo/loginbackgroundimage&#039;;                                                                                     &lt;br /&gt;
    $title = get_string(&#039;loginbackgroundimage&#039;, &#039;theme_photo&#039;);                                                                     &lt;br /&gt;
    $description = get_string(&#039;loginbackgroundimage_desc&#039;, &#039;theme_photo&#039;);                                                          &lt;br /&gt;
    // This creates the new setting.                                                                                                &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;loginbackgroundimage&#039;);                             &lt;br /&gt;
    // This means that theme caches will automatically be cleared when this setting is changed.                                     &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    // We always have to add the setting to a page for it to have any effect.                                                       &lt;br /&gt;
    $page-&amp;gt;add($setting);       &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need to add new lang strings to our language file.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lang/en/theme_photo.php&amp;quot;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Background image for login page.                                                                                                 &lt;br /&gt;
$string[&#039;loginbackgroundimage&#039;] = &#039;Login page background image&#039;;                                                                    &lt;br /&gt;
// Background image for login page.                                                                                                 &lt;br /&gt;
$string[&#039;loginbackgroundimage_desc&#039;] = &#039;An image that will be stretched to fill the background of the login page.&#039;;                 &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have a new setting that lets us upload a file - but it doesn&#039;t actually do anything yet. We need to update the theme to set this image background on the login page.&lt;br /&gt;
&lt;br /&gt;
In order to change the SCSS for our theme we will add 2 additional SCSS files and include them before and after our main scss.&lt;br /&gt;
&lt;br /&gt;
We already have a function in our lib.php file which fetches the main SCSS for our theme. This is a good point to include additional SCSS files. We can add 2 lines to the end of this function to achieve this.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        // This preset file was fetched from the file area for theme_photo and not theme_boost (see the line above).                &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Pre CSS - this is loaded AFTER any prescss from the setting but before the main scss.                                        &lt;br /&gt;
    $pre = file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/photo/scss/pre.scss&#039;);                                                         &lt;br /&gt;
    // Post CSS - this is loaded AFTER the main scss but before the extra scss from the setting.                                    &lt;br /&gt;
    $post = file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/photo/scss/post.scss&#039;);                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Combine them together.                                                                                                       &lt;br /&gt;
    return $pre . &amp;quot;\n&amp;quot; . $scss . &amp;quot;\n&amp;quot; . $post;                                                                                      &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;scss/pre.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
// Pre SCSS for the theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;scss/post.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
// Post SCSS for the theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Why do we use pre and post SCSS? ====&lt;br /&gt;
SCSS/SASS is a powerful language for creating CSS. It supports variables, functions, loops just like php. For lots of information and an introduction to SCSS read about [https://en.wikipedia.org/wiki/Sass_(stylesheet_language) Sass on wikipedia]. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pre SCSS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In Boost we use many variables when creating style rules.&lt;br /&gt;
&lt;br /&gt;
When declaring a variable in SCSS - it is best practice to define it like this:&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
$mycoolcolour: #FF0 !default;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this means is - if this variable is not defined already - set it to the hex value &#039;#FF0&#039;;&lt;br /&gt;
&lt;br /&gt;
So by setting this variable in some PRE scss we can override the default value of this variable everywhere it is used. Boost is built with the [https://v4-alpha.getbootstrap.com/ Bootstrap 4 (Alpha 4)] CSS Framework. This is a framework which uses SCSS to provide many extremely useful layouts and components which can be reused without adding specific CSS rules to style every page. Because bootstrap consistently uses variables we can customise many of these components easily by setting the value of the variables before we include the Bootstrap SCSS files.&lt;br /&gt;
&lt;br /&gt;
Many variables are available in /theme/boost/scss/bootstrap/_variables.scss - as an example we can change the look of all buttons and input fields with this one variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
$border-radius: 8px;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Post SCSS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Post SCSS is useful for defining full CSS rules. Because they are included last, they override any previous matching selector with the same [https://en.wikipedia.org/wiki/Cascading_Style_Sheets#Specificity Specificity].&lt;br /&gt;
&lt;br /&gt;
=== Tips for customising Moodle with SCSS (or CSS) ===&lt;br /&gt;
Some handy things to know when you are new to theming is that Moodle adds some classes to every page that helps you target a specific page or set of pages with some style rules. &lt;br /&gt;
&lt;br /&gt;
If you inspect a moodle page and look at the body tag you will see a long list of classes e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code html&amp;gt;&lt;br /&gt;
&amp;lt;body id=&amp;quot;page-course-view-weeks&amp;quot; class=&amp;quot;format-weeks  path-course path-course-view safari dir-ltr lang-en yui-skin-sam yui3-skin-sam damyon-per-in-moodle-com--stable_master pagelayout-course course-11 context-497 category-1 drawer-open-left jsenabled&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can see from this example that each page gets an id. This is a simplified representation of the current page in the navigation. In this example we are looking at the course page and this course is using the weeks format. &lt;br /&gt;
&lt;br /&gt;
The classes on the body tag can also be used to target a page or set of pages.&lt;br /&gt;
* &amp;lt;code&amp;gt;format-weeks&amp;lt;/code&amp;gt; The course format&lt;br /&gt;
* &amp;lt;code&amp;gt;path-course path-course-view&amp;lt;/code&amp;gt; The parts of the bread-crumb leading up to the current page (The current page is what goes in the id)&lt;br /&gt;
* &amp;lt;code&amp;gt;safari&amp;lt;/code&amp;gt; Some server side guessing of the browser type - it&#039;s not accurate so I would not rely on it&lt;br /&gt;
* &amp;lt;code&amp;gt;dir-ltr&amp;lt;/code&amp;gt; The direction of the current language for the page ( dir-rtl for RTL languages )&lt;br /&gt;
* &amp;lt;code&amp;gt;lang-en&amp;lt;/code&amp;gt; The current language of the page&lt;br /&gt;
* &amp;lt;code&amp;gt;yui*&amp;lt;/code&amp;gt; Legacy yui classes - ignore these&lt;br /&gt;
* &amp;lt;code&amp;gt;damyon-per-in-moodle-com--stable_master&amp;lt;/code&amp;gt; The current hostname for the site + the site name&lt;br /&gt;
* &amp;lt;code&amp;gt;pagelayout-course&amp;lt;/code&amp;gt; The layout type for the current page&lt;br /&gt;
* &amp;lt;code&amp;gt;course-11&amp;lt;/code&amp;gt; The id of the current course&lt;br /&gt;
* &amp;lt;code&amp;gt;context-497&amp;lt;/code&amp;gt; The current context id&lt;br /&gt;
* &amp;lt;code&amp;gt;category-1&amp;lt;/code&amp;gt; The category for the current course&lt;br /&gt;
* &amp;lt;code&amp;gt;drawer-open-left&amp;lt;/code&amp;gt; Added / removed when the navigation drawer is opened / closed in Boost&lt;br /&gt;
* &amp;lt;code&amp;gt;jsenabled&amp;lt;/code&amp;gt; True if the browser supports javascript&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/dev/Themes_overview#.3Cbody.3E_CSS_id_and_classes Read about Body id and classes].&lt;br /&gt;
&lt;br /&gt;
In our example the page layout is the most useful here as we have a specific page layout for login pages. We can now craft a rule that applies a background image only to login pages using &amp;quot;body.pagelayout-login&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How do we refer to an image in SCSS ? ===&lt;br /&gt;
So now we can add a rule to the post.scss which will set the background image for the login page. First we need to know how to construct a url to the background images from our stylesheet. &lt;br /&gt;
&lt;br /&gt;
In stylesheets in Moodle we can use a special pix tag to refer to images from our theme. The rule to attach the background image looks like this:&lt;br /&gt;
&#039;&#039;scss/post.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
body.pagelayout-login {                                                                                                             &lt;br /&gt;
    background-image: url([[pix:theme_photo|loginbackgroundimage]]);                                                                &lt;br /&gt;
    background-size: cover;                                                                                                         &lt;br /&gt;
}                          &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are 2 important parts to this tag (the bit in square brackets). The first is &amp;quot;theme_photo&amp;quot;. In this case we are passing a component name, the image serving code in theme_config::resolve_image_location() will then look for an image file in several locations. One of these is in &amp;quot;$CFG-&amp;gt;dataroot/pix_plugins/$type/$plugin/$image&amp;quot;. We can use this to make sure the image gets served correctly by copying the file saved in the setting to this location every time it is updated. (There is an alterative way we could do this by implementing pluginfile.php in our theme - which you can read about in the [[File API]] ).&lt;br /&gt;
&lt;br /&gt;
If we had just passed the value &amp;quot;theme&amp;quot; the image serving code would have looked for the image in the &amp;quot;pix&amp;quot; folder of our theme.&lt;br /&gt;
&lt;br /&gt;
So - we need this final change to copy the image file into our dataroot each time the setting is changed.&lt;br /&gt;
&lt;br /&gt;
In the settings file we will update the callback to a new function which we will define in our lib.php.&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Login page background setting.                                                                                               &lt;br /&gt;
    // We use variables for readability.                                                                                            &lt;br /&gt;
    $name = &#039;theme_photo/loginbackgroundimage&#039;;                                                                                     &lt;br /&gt;
    $title = get_string(&#039;loginbackgroundimage&#039;, &#039;theme_photo&#039;);                                                                     &lt;br /&gt;
    $description = get_string(&#039;loginbackgroundimage_desc&#039;, &#039;theme_photo&#039;);                                                          &lt;br /&gt;
    // This creates the new setting.                                                                                                &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;loginbackgroundimage&#039;);                             &lt;br /&gt;
    // This function will copy the image into the data_root location it can be served from.                                         &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_photo_update_settings_images&#039;);                                                            &lt;br /&gt;
    // We always have to add the setting to a page for it to have any effect.                                                       &lt;br /&gt;
    $page-&amp;gt;add($setting);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_update_settings_images($settingname) {                                                                         &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // The setting name that was updated comes as a string like &#039;s_theme_photo_loginbackgroundimage&#039;.                               &lt;br /&gt;
    // We split it on &#039;_&#039; characters.                                                                                               &lt;br /&gt;
    $parts = explode(&#039;_&#039;, $settingname);                                                                                            &lt;br /&gt;
    // And get the last one to get the setting name..                                                                               &lt;br /&gt;
    $settingname = end($parts);                                                                                                     &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Admin settings are stored in system context.                                                                                 &lt;br /&gt;
    $syscontext = context_system::instance();                                                                                       &lt;br /&gt;
    // This is the component name the setting is stored in.                                                                         &lt;br /&gt;
    $component = &#039;theme_photo&#039;;                                                                                                     &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // This is the value of the admin setting which is the filename of the uploaded file.                                           &lt;br /&gt;
    $filename = get_config($component, $settingname);                                                                               &lt;br /&gt;
    // We extract the file extension because we want to preserve it.                                                                &lt;br /&gt;
    $extension = substr($filename, strrpos($filename, &#039;.&#039;) + 1);                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // This is the path in the moodle internal file system.                                                                         &lt;br /&gt;
    $fullpath = &amp;quot;/{$syscontext-&amp;gt;id}/{$component}/{$settingname}/0{$filename}&amp;quot;;                                                      &lt;br /&gt;
    // Get an instance of the moodle file storage.                                                                                  &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
    // This is an efficient way to get a file if we know the exact path.                                                            &lt;br /&gt;
    if ($file = $fs-&amp;gt;get_file_by_hash(sha1($fullpath))) {                                                                           &lt;br /&gt;
        // We got the stored file - copy it to dataroot.                                                                            &lt;br /&gt;
        // This location matches the searched for location in theme_config::resolve_image_location.                                 &lt;br /&gt;
        $pathname = $CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039; . $settingname . &#039;.&#039; . $extension;                                 &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // This pattern matches any previous files with maybe different file extensions.                                            &lt;br /&gt;
        $pathpattern = $CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039; . $settingname . &#039;.*&#039;;                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Make sure this dir exists.                                                                                               &lt;br /&gt;
        @mkdir($CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039;, $CFG-&amp;gt;directorypermissions, true);                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Delete any existing files for this setting.                                                                              &lt;br /&gt;
        foreach (glob($pathpattern) as $filename) {                                                                                 &lt;br /&gt;
            @unlink($filename);                                                                                                     &lt;br /&gt;
        }                                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Copy the current file to this location.                                                                                  &lt;br /&gt;
        $file-&amp;gt;copy_content_to($pathname);                                                                                          &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Reset theme caches.                                                                                                          &lt;br /&gt;
    theme_reset_all_caches();                                                                                                       &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I won&#039;t show it here - but it is now easy to add a new background image setting for every layout type. I can re-use this theme_photo_update_settings_images callback for each one - so all I have to do is add the setting to the settings.php file, add the SCSS rule to the scss/post.scss file and add the lang strings to the language file.&lt;br /&gt;
&lt;br /&gt;
Thats it for this tutorial, but there are [[:Category:Themes| more Themes docs]] to browse.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Themes]]&lt;/div&gt;</summary>
		<author><name>Meeth</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Creating_a_theme_based_on_boost&amp;diff=57724</id>
		<title>Creating a theme based on boost</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Creating_a_theme_based_on_boost&amp;diff=57724"/>
		<updated>2020-07-20T15:01:59Z</updated>

		<summary type="html">&lt;p&gt;Meeth: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 3.2}}&lt;br /&gt;
{{Template:Themes}}&lt;br /&gt;
&lt;br /&gt;
This is a tutorial for how to create a new theme in any version of Moodle from 3.2 and later.&lt;br /&gt;
&lt;br /&gt;
Moodle 3.2 introduced a new core theme named &amp;quot;Boost&amp;quot; which is a great starting point for themers wanting to build a modern Moodle theme utilising all the latest features available to themes in Moodle.  If you aren&#039;t sure where to start, then START HERE!  :-)&lt;br /&gt;
&lt;br /&gt;
== Getting started ==&lt;br /&gt;
What is a theme? A theme in Moodle is just another type of plugin that can be developed. Themes are responsible for setting up the structure of each page and have the ability to customise the output of any page in Moodle.&lt;br /&gt;
&lt;br /&gt;
This tutorial is based on a working theme named &amp;quot;theme_photo&amp;quot; you can download it or view the source code for it here: https://github.com/damyon/moodle-theme_photo&lt;br /&gt;
&lt;br /&gt;
=== Choosing a name ===&lt;br /&gt;
Your new theme will need a name. Try and think of something short and memorable - and make sure it is not a name that has already been used by someone else. A quick search on the moodle.org/plugins can save you a lot of work renaming things later.&lt;br /&gt;
&lt;br /&gt;
Lets call our new example theme &amp;quot;photo&amp;quot; as we will add some settings to allow &amp;quot;photos&amp;quot; in various places in Moodle.&lt;br /&gt;
&lt;br /&gt;
=== Starting files ===&lt;br /&gt;
As a plugin, themes must start with the basic structure of a plugin in Moodle. See https://docs.moodle.org/dev/Tutorial#The_skeleton_of_your_plugin for an overview of the files common to all plugins in Moodle.&lt;br /&gt;
&lt;br /&gt;
Following this guide we can start creating our theme. First we create the folder for the new theme under &amp;quot;/theme/&amp;quot; folder in the Moodle root directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
/theme/photo/&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we need to add some standard plugin files to our theme. First is version.php&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/theme/photo/version.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the version of the plugin.                                                                                               &lt;br /&gt;
$plugin-&amp;gt;version = &#039;2016102100&#039;;                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the version of Moodle this plugin requires.                                                                              &lt;br /&gt;
$plugin-&amp;gt;requires = &#039;2016070700&#039;;                                                                                                   &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the component name of the plugin - it always starts with &#039;theme_&#039;                                                        &lt;br /&gt;
// for themes and should be the same as the name of the folder.                                                                     &lt;br /&gt;
$plugin-&amp;gt;component = &#039;theme_photo&#039;;                                                                                                 &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a list of plugins, this plugin depends on (and their versions).                                                          &lt;br /&gt;
$plugin-&amp;gt;dependencies = [                                                                                                           &lt;br /&gt;
    &#039;theme_boost&#039; =&amp;gt; &#039;2016102100&#039;                                                                                                   &lt;br /&gt;
];                                                                              &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need a language file so that all our strings can be translated into different languages. The name of this file is the component name of our plugin and it sits in the lang/en/ folder for our plugin. We can include translations of our plugin, but we can also provide translations via the https://lang.moodle.org/ website once our plugin has been published to the plugins database at http://www.moodle.org/plugins/.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/theme/photo/lang/en/theme_photo.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// A description shown in the admin theme selector.                                                                                 &lt;br /&gt;
$string[&#039;choosereadme&#039;] = &#039;Theme photo is a child theme of Boost. It adds the ability to upload background photos.&#039;;                &lt;br /&gt;
// The name of our plugin.                                                                                                          &lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Photo&#039;;                                                                                                    &lt;br /&gt;
// We need to include a lang string for each block region.                                                                          &lt;br /&gt;
$string[&#039;region-side-pre&#039;] = &#039;Right&#039;;                                         &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Theme specific files ===&lt;br /&gt;
Theme plugins have a few more standard files they need to define. &lt;br /&gt;
&lt;br /&gt;
Themes require a favicon file to show in the address bar. See [[http://docs.moodle.org/en/Favicon Favicon]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;pix/favicon.ico&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(Image file not shown).&lt;br /&gt;
&lt;br /&gt;
Themes also require an example screenshot to be displayed in the theme selector.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;pix/screenshot.jpg&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(Image file not shown).&lt;br /&gt;
&lt;br /&gt;
Themes require a lib.php file. This file contains callbacks used by various API&#039;s in Moodle. Initially this file can be empty, but as we add features to our theme we will need to add some functions here.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
// We will add callbacks here as we add features to our theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Theme config goes in a config.php file. This is one of the most important files in our theme. Once we add this file we will be ready to test our theme for the first time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
// $THEME is defined before this page is included and we can define settings by adding properties to this global object.            &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// The first setting we need is the name of the theme. This should be the last part of the component name, and the same             &lt;br /&gt;
// as the directory name for our theme.                                                                                             &lt;br /&gt;
$THEME-&amp;gt;name = &#039;photo&#039;;                                                                                                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This setting list the style sheets we want to include in our theme. Because we want to use SCSS instead of CSS - we won&#039;t        &lt;br /&gt;
// list any style sheets. If we did we would list the name of a file in the /style/ folder for our theme without any css file      &lt;br /&gt;
// extensions.                                                                                                                      &lt;br /&gt;
$THEME-&amp;gt;sheets = [];                                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a setting that can be used to provide some styling to the content in the TinyMCE text editor. This is no longer the      &lt;br /&gt;
// default text editor and &amp;quot;Atto&amp;quot; does not need this setting so we won&#039;t provide anything. If we did it would work the same         &lt;br /&gt;
// as the previous setting - listing a file in the /styles/ folder.                                                                 &lt;br /&gt;
$THEME-&amp;gt;editor_sheets = [];                                                                                                         &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a critical setting. We want to inherit from theme_boost because it provides a great starting point for SCSS bootstrap4   &lt;br /&gt;
// themes. We could add more than one parent here to inherit from multiple parents, and if we did they would be processed in        &lt;br /&gt;
// order of importance (later themes overriding earlier ones). Things we will inherit from the parent theme include                 &lt;br /&gt;
// styles and mustache templates and some (not all) settings.                                                                       &lt;br /&gt;
$THEME-&amp;gt;parents = [&#039;boost&#039;];                                                                                                        &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// A dock is a way to take blocks out of the page and put them in a persistent floating area on the side of the page. Boost         &lt;br /&gt;
// does not support a dock so we won&#039;t either - but look at bootstrapbase for an example of a theme with a dock.                    &lt;br /&gt;
$THEME-&amp;gt;enable_dock = false;                                                                                                        &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is an old setting used to load specific CSS for some YUI JS. We don&#039;t need it in Boost based themes because Boost           &lt;br /&gt;
// provides default styling for the YUI modules that we use. It is not recommended to use this setting anymore.                     &lt;br /&gt;
$THEME-&amp;gt;yuicssmodules = array();                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// Most themes will use this rendererfactory as this is the one that allows the theme to override any other renderer.               &lt;br /&gt;
$THEME-&amp;gt;rendererfactory = &#039;theme_overridden_renderer_factory&#039;;                                                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a list of blocks that are required to exist on all pages for this theme to function correctly. For example               &lt;br /&gt;
// bootstrap base requires the settings and navigation blocks because otherwise there would be no way to navigate to all the        &lt;br /&gt;
// pages in Moodle. Boost does not require these blocks because it provides other ways to navigate built into the theme.            &lt;br /&gt;
$THEME-&amp;gt;requiredblocks = &#039;&#039;;   &lt;br /&gt;
&lt;br /&gt;
// This is a feature that tells the blocks library not to use the &amp;quot;Add a block&amp;quot; block. We don&#039;t want this in boost based themes because&lt;br /&gt;
// it forces a block region into the page when editing is enabled and it takes up too much room.&lt;br /&gt;
$THEME-&amp;gt;addblockposition = BLOCK_ADDBLOCK_POSITION_FLATNAV;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ready set go! ===&lt;br /&gt;
If you have been following along - now we are at the point where we can actually install and test our new theme. Try it now by visiting the admin notifications page to install the new plugin, and then choosing the new theme from the theme selector.&lt;br /&gt;
&lt;br /&gt;
[[https://docs.moodle.org/en/Standard_themes#Theme_selector Theme selector]]&lt;br /&gt;
&lt;br /&gt;
When you choose the new theme - you will find that it looks exactly the same as Boost. At this point with our minimal configuration - we are inheriting almost everything from our parent theme including styles and templates. You will notice though that we don&#039;t inherit the settings from our parent theme. If you choose a different preset in Boost - it is not applied in this child theme.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&lt;br /&gt;
Note: make sure your config.php file contains $THEME-&amp;gt;hidefromselector = false; (or at least set to false) or else, your theme wont show up in theme selector.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What if I want the settings too? ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&lt;br /&gt;
This section is included for completeness - but it is not recommended for themes to utilise settings from their parents. To find out how to duplicate the settings from the parent theme so they operate independently skip to [[#Duplicate the settings from Boost]].&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If I want the settings from Boost to apply to my child theme as well I need to know a bit about how each of the settings in Boost is applied to make them work in my child theme.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Setting 1 - preset.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;preset&amp;quot; file is the file that is used as the main file for scss compilation. In Boost this is controlled by the theme config value:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {&lt;br /&gt;
    return theme_boost_get_main_scss_content($theme);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_boost&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this function is doing is checking for a theme setting &amp;quot;preset&amp;quot; and either fetching the file from Moodles internal file storage, or from the /preset/ folder. The function then returns the contents of this file.&lt;br /&gt;
&lt;br /&gt;
It does not automatically work for our child theme because we have no setting named &amp;quot;preset&amp;quot; in our child theme and this code is not searching the theme parents for the setting. If we wanted it to apply we could do this in our child theme:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This setting defines the main scss file for our theme to be compiled. We could set it to a static file in the scss folder or to a function which returns the SCSS based on theme settings.&lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {&lt;br /&gt;
&lt;br /&gt;
    // We need to load the config for our parent theme because that is where the preset setting is defined.&lt;br /&gt;
    $parentconfig = theme_config::load(&#039;boost&#039;);&lt;br /&gt;
    // Call a function from our parent themes lib.php file to fetch the content of the themes main SCSS file based on it&#039;s own config, not ours.&lt;br /&gt;
    return theme_boost_get_main_scss_content($parentconfig);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings 2+3 brandcolor + scsspre&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The way these settings work is they generate a chunk of SCSS to be prepended to the main scss file. In boost they work like this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;prescsscallback = &#039;theme_boost_get_pre_scss&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_pre_scss($theme) {                                                                                         &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $configurable = [                                                                                                               &lt;br /&gt;
        // Config key =&amp;gt; [variableName, ...].                                                                                       &lt;br /&gt;
        &#039;brandcolor&#039; =&amp;gt; [&#039;brand-primary&#039;],                                                                                          &lt;br /&gt;
    ];                                                                                                                              &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Prepend variables first.                                                                                                     &lt;br /&gt;
    foreach ($configurable as $configkey =&amp;gt; $targets) {                                                                             &lt;br /&gt;
        $value = isset($theme-&amp;gt;settings-&amp;gt;{$configkey}) ? $theme-&amp;gt;settings-&amp;gt;{$configkey} : null;                                     &lt;br /&gt;
        if (empty($value)) {                                                                                                        &lt;br /&gt;
            continue;                                                                                                               &lt;br /&gt;
        }                                                                                                                           &lt;br /&gt;
        array_map(function($target) use (&amp;amp;$scss, $value) {                                                                          &lt;br /&gt;
            $scss .= &#039;$&#039; . $target . &#039;: &#039; . $value . &amp;quot;;\n&amp;quot;;                                                                         &lt;br /&gt;
        }, (array) $targets);                                                                                                       &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Prepend pre-scss.                                                                                                            &lt;br /&gt;
    if (!empty($theme-&amp;gt;settings-&amp;gt;scsspre)) {                                                                                        &lt;br /&gt;
        $scss .= $theme-&amp;gt;settings-&amp;gt;scsspre;                                                                                         &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}  &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this code is doing is: &lt;br /&gt;
* looping over a list of theme settings that map to a SCSS variable and building some SCSS to initialise that variable from the setting. In Boost there is only one * brandprimary - but if we wanted to expose more bootstrap variables as theme settings we could use this function as a template in our child theme and add more settings to the $configurable array.&lt;br /&gt;
* Adding all of the raw SCSS from the scsspre theme setting&lt;br /&gt;
* Returning the whole thing as a string to be added before the main scss file.&lt;br /&gt;
&lt;br /&gt;
If we want this code to work in our child theme, using the settings from Boost we could do this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is a function that returns some SCSS as a string to prepend to the main SCSS file.                                          &lt;br /&gt;
$THEME-&amp;gt;prescsscallback = &#039;theme_photo_get_pre_scss&#039;;               &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Function to return the SCSS to prepend to our main SCSS for this theme.&lt;br /&gt;
// Note the function name starts with the component name because this is a global function and we don&#039;t want namespace clashes.&lt;br /&gt;
function theme_photo_get_pre_scss($theme) {&lt;br /&gt;
    // Load the settings from the parent.                                                                                           &lt;br /&gt;
    $theme = theme_config::load(&#039;boost&#039;);                                                                                           &lt;br /&gt;
    // Call the parent themes get_pre_scss function.                                                                                &lt;br /&gt;
    return theme_boost_get_pre_scss($theme);                         &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Setting 4 scss (post)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The final setting from Boost is a raw text field which adds SCSS to the end of the main SCSS file. This is a useful place to add style rules as they will override previously defined styles with the same specificity. It is applied in Boost by the following lines:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;extrascsscallback = &#039;theme_boost_get_extra_scss&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_extra_scss($theme) {                                                                                       &lt;br /&gt;
    return !empty($theme-&amp;gt;settings-&amp;gt;scss) ? $theme-&amp;gt;settings-&amp;gt;scss : &#039;&#039;;                                                            &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is just returning the value of the setting as a string.&lt;br /&gt;
&lt;br /&gt;
To make this setting apply in our child theme too - we use similar code to the previous sections.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is a function that returns some SCSS as a string to append to the main SCSS file.                                          &lt;br /&gt;
$THEME-&amp;gt;extrascsscallback = &#039;theme_photo_get_extra_scss&#039;;               &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Function to return the SCSS to append to our main SCSS for this theme.&lt;br /&gt;
// Note the function name starts with the component name because this is a global function and we don&#039;t want namespace clashes.&lt;br /&gt;
function theme_photo_get_extra_scss($theme) {&lt;br /&gt;
    // Load the settings from the parent.                                                                                           &lt;br /&gt;
    $theme = theme_config::load(&#039;boost&#039;);                                                                                           &lt;br /&gt;
    // Call the parent themes get_extra_scss function.                                                                                &lt;br /&gt;
    return theme_boost_get_extra_scss($theme);                         &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Duplicate the settings from Boost  ===&lt;br /&gt;
&lt;br /&gt;
This is the recommended way to extend boost as your child theme will not be affected by changes to the Boost settings, and both themes can be in use with different settings applied.&lt;br /&gt;
&lt;br /&gt;
All that needs to happen is to create theme settings in the child theme that match each of the settings in the parent theme. You will need to add matching language strings for each of these settings in the language file.&lt;br /&gt;
&lt;br /&gt;
This example shows how to do it - We are re-using the nice looking theme_boost_admin_settingspage_tabs class from boost and creating duplicate versions of each of the settings.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is used for performance, we don&#039;t need to know about these settings on every page in Moodle, only when                      &lt;br /&gt;
// we are looking at the admin settings pages.                                                                                      &lt;br /&gt;
if ($ADMIN-&amp;gt;fulltree) {                                                                                                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Boost provides a nice setting page which splits settings onto separate tabs. We want to use it here.                         &lt;br /&gt;
    $settings = new theme_boost_admin_settingspage_tabs(&#039;themesettingphoto&#039;, get_string(&#039;configtitle&#039;, &#039;theme_photo&#039;));             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Each page is a tab - the first is the &amp;quot;General&amp;quot; tab.                                                                         &lt;br /&gt;
    $page = new admin_settingpage(&#039;theme_photo_general&#039;, get_string(&#039;generalsettings&#039;, &#039;theme_photo&#039;));                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Replicate the preset setting from boost.                                                                                     &lt;br /&gt;
    $name = &#039;theme_photo/preset&#039;;                                                                                                   &lt;br /&gt;
    $title = get_string(&#039;preset&#039;, &#039;theme_photo&#039;);                                                                                   &lt;br /&gt;
    $description = get_string(&#039;preset_desc&#039;, &#039;theme_photo&#039;);                                                                        &lt;br /&gt;
    $default = &#039;default.scss&#039;;                                                                                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // We list files in our own file area to add to the drop down. We will provide our own function to                              &lt;br /&gt;
    // load all the presets from the correct paths.                                                                                 &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
    $files = $fs-&amp;gt;get_area_files($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;itemid, filepath, filename&#039;, false);                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $choices = [];                                                                                                                  &lt;br /&gt;
    foreach ($files as $file) {                                                                                                     &lt;br /&gt;
        $choices[$file-&amp;gt;get_filename()] = $file-&amp;gt;get_filename();                                                                    &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
    // These are the built in presets from Boost.                                                                                   &lt;br /&gt;
    $choices[&#039;default.scss&#039;] = &#039;default.scss&#039;;                                                                                      &lt;br /&gt;
    $choices[&#039;plain.scss&#039;] = &#039;plain.scss&#039;;                                                                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $setting = new admin_setting_configselect($name, $title, $description, $default, $choices);                                     &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Preset files setting.                                                                                                        &lt;br /&gt;
    $name = &#039;theme_photo/presetfiles&#039;;                                                                                              &lt;br /&gt;
    $title = get_string(&#039;presetfiles&#039;,&#039;theme_photo&#039;);                                                                               &lt;br /&gt;
    $description = get_string(&#039;presetfiles_desc&#039;, &#039;theme_photo&#039;);                                                                   &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;preset&#039;, 0,                                         &lt;br /&gt;
        array(&#039;maxfiles&#039; =&amp;gt; 20, &#039;accepted_types&#039; =&amp;gt; array(&#039;.scss&#039;)));                                                               &lt;br /&gt;
    $page-&amp;gt;add($setting);     &lt;br /&gt;
&lt;br /&gt;
    // Variable $brand-color.                                                                                                       &lt;br /&gt;
    // We use an empty default value because the default colour should come from the preset.                                        &lt;br /&gt;
    $name = &#039;theme_photo/brandcolor&#039;;                                                                                               &lt;br /&gt;
    $title = get_string(&#039;brandcolor&#039;, &#039;theme_photo&#039;);                                                                               &lt;br /&gt;
    $description = get_string(&#039;brandcolor_desc&#039;, &#039;theme_photo&#039;);                                                                    &lt;br /&gt;
    $setting = new admin_setting_configcolourpicker($name, $title, $description, &#039;&#039;);                                               &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Must add the page after definiting all the settings!                                                                         &lt;br /&gt;
    $settings-&amp;gt;add($page);                                                                                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Advanced settings.                                                                                                           &lt;br /&gt;
    $page = new admin_settingpage(&#039;theme_photo_advanced&#039;, get_string(&#039;advancedsettings&#039;, &#039;theme_photo&#039;));                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Raw SCSS to include before the content.                                                                                      &lt;br /&gt;
    $setting = new admin_setting_configtextarea(&#039;theme_photo/scsspre&#039;,                                                              &lt;br /&gt;
        get_string(&#039;rawscsspre&#039;, &#039;theme_photo&#039;), get_string(&#039;rawscsspre_desc&#039;, &#039;theme_photo&#039;), &#039;&#039;, PARAM_RAW);                      &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Raw SCSS to include after the content.                                                                                       &lt;br /&gt;
    $setting = new admin_setting_configtextarea(&#039;theme_photo/scss&#039;, get_string(&#039;rawscss&#039;, &#039;theme_photo&#039;),                           &lt;br /&gt;
        get_string(&#039;rawscss_desc&#039;, &#039;theme_photo&#039;), &#039;&#039;, PARAM_RAW);                                                                  &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $settings-&amp;gt;add($page);                                                                                                          &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lang/en/theme_photo.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
// The name of the second tab in the theme settings.                                                                                &lt;br /&gt;
$string[&#039;advancedsettings&#039;] = &#039;Advanced settings&#039;;                                                                                  &lt;br /&gt;
// The brand colour setting.                                                                                                        &lt;br /&gt;
$string[&#039;brandcolor&#039;] = &#039;Brand colour&#039;;                                                                                             &lt;br /&gt;
// The brand colour setting description.                                                                                            &lt;br /&gt;
$string[&#039;brandcolor_desc&#039;] = &#039;The accent colour.&#039;;     &lt;br /&gt;
// A description shown in the admin theme selector.                                                                                 &lt;br /&gt;
$string[&#039;choosereadme&#039;] = &#039;Theme photo is a child theme of Boost. It adds the ability to upload background photos.&#039;;                &lt;br /&gt;
// Name of the settings pages.                                                                                                      &lt;br /&gt;
$string[&#039;configtitle&#039;] = &#039;Photo settings&#039;;                                                                                          &lt;br /&gt;
// Name of the first settings tab.                                                                                                  &lt;br /&gt;
$string[&#039;generalsettings&#039;] = &#039;General settings&#039;;                                                                                    &lt;br /&gt;
// The name of our plugin.                                                                                                          &lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Photo&#039;;                                                                                                    &lt;br /&gt;
// Preset files setting.                                                                                                            &lt;br /&gt;
$string[&#039;presetfiles&#039;] = &#039;Additional theme preset files&#039;;                                                                           &lt;br /&gt;
// Preset files help text.                                                                                                          &lt;br /&gt;
$string[&#039;presetfiles_desc&#039;] = &#039;Preset files can be used to dramatically alter the appearance of the theme. See &amp;lt;a href=https://docs.moodle.org/dev/Boost_Presets&amp;gt;Boost presets&amp;lt;/a&amp;gt; for information on creating and sharing your own preset files, and see the &amp;lt;a href=http://moodle.net/boost&amp;gt;Presets repository&amp;lt;/a&amp;gt; for presets that others have shared.&#039;;&lt;br /&gt;
// Preset setting.                                                                                                                  &lt;br /&gt;
$string[&#039;preset&#039;] = &#039;Theme preset&#039;;                                                                                                 &lt;br /&gt;
// Preset help text.                                                                                                                &lt;br /&gt;
$string[&#039;preset_desc&#039;] = &#039;Pick a preset to broadly change the look of the theme.&#039;;                                                  &lt;br /&gt;
// Raw SCSS setting.                                                                                                                &lt;br /&gt;
$string[&#039;rawscss&#039;] = &#039;Raw SCSS&#039;;                                                                                                    &lt;br /&gt;
// Raw SCSS setting help text.                                                                                                      &lt;br /&gt;
$string[&#039;rawscss_desc&#039;] = &#039;Use this field to provide SCSS or CSS code which will be injected at the end of the style sheet.&#039;;       &lt;br /&gt;
// Raw initial SCSS setting.                                                                                                        &lt;br /&gt;
$string[&#039;rawscsspre&#039;] = &#039;Raw initial SCSS&#039;;                                                                                         &lt;br /&gt;
// Raw initial SCSS setting help text.                                                                                              &lt;br /&gt;
$string[&#039;rawscsspre_desc&#039;] = &#039;In this field you can provide initialising SCSS code, it will be injected before everything else. Most of the time you will use this setting to define variables.&#039;;&lt;br /&gt;
// We need to include a lang string for each block region.                                                                          &lt;br /&gt;
$string[&#039;region-side-pre&#039;] = &#039;Right&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We aren&#039;t quite there yet as you will notice if you try and upload a preset file and then choose it. The &amp;quot;theme_boost_get_main_scss_content&amp;quot; function from Boost is expecting the preset files to be stored in a file area for theme_boost only. We need to add this function to our own theme and tweak it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is the function that returns the SCSS source for the main file in our theme. We override the boost version because          &lt;br /&gt;
// we want to allow presets uploaded to our own theme file area to be selected in the preset list.                                  &lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {                                                                                                   &lt;br /&gt;
    return theme_photo_get_main_scss_content($theme);                                                                               &lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        // This preset file was fetched from the file area for theme_photo and not theme_boost (see the line above).                &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}             &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Stop and try it out ===&lt;br /&gt;
So now what is working and what isn&#039;t. Well - everything should be working and you should have a nice new theme extending boost with it&#039;s own settings pages. When Boost gets updates for bug fixes your new theme will inherit those fixes as it inherits all the SCSS and templates from theme boost. In addition your new theme will accept preset files and supports all the same features and settings as boost, ready to add more.&lt;br /&gt;
&lt;br /&gt;
== Take it further ==&lt;br /&gt;
Now we have our very nice starting point we can start changing or adding features, customising templates and output or tweaking the SCSS.&lt;br /&gt;
&lt;br /&gt;
=== Add some new settings ===&lt;br /&gt;
&lt;br /&gt;
From this point in the tutorial we will start adding features to our theme to extend it and make it AWESOME!&lt;br /&gt;
&lt;br /&gt;
Lets start with a new setting to set a background image on the login page. As you saw earlier, our theme defines it&#039;s list of settings in a file called settings.php. See [[Admin settings]] for more information about adding admin settings to any plugin. All of the different kinds of admin settings can be found in lib/adminlib.php. In our case we will want to add a setting which allows an admin to upload an image file. This is an &amp;quot;admin_setting_configstoredfile&amp;quot; and we add it to our theme by adding  this code to the settings.php file (inside the &amp;quot;if ($ADMIN-&amp;gt;fulltree) {&amp;quot; condition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    // Login page background setting.                                                                                               &lt;br /&gt;
    // We use variables for readability.                                                                                            &lt;br /&gt;
    $name = &#039;theme_photo/loginbackgroundimage&#039;;                                                                                     &lt;br /&gt;
    $title = get_string(&#039;loginbackgroundimage&#039;, &#039;theme_photo&#039;);                                                                     &lt;br /&gt;
    $description = get_string(&#039;loginbackgroundimage_desc&#039;, &#039;theme_photo&#039;);                                                          &lt;br /&gt;
    // This creates the new setting.                                                                                                &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;loginbackgroundimage&#039;);                             &lt;br /&gt;
    // This means that theme caches will automatically be cleared when this setting is changed.                                     &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    // We always have to add the setting to a page for it to have any effect.                                                       &lt;br /&gt;
    $page-&amp;gt;add($setting);       &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need to add new lang strings to our language file.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lang/en/theme_photo.php&amp;quot;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Background image for login page.                                                                                                 &lt;br /&gt;
$string[&#039;loginbackgroundimage&#039;] = &#039;Login page background image&#039;;                                                                    &lt;br /&gt;
// Background image for login page.                                                                                                 &lt;br /&gt;
$string[&#039;loginbackgroundimage_desc&#039;] = &#039;An image that will be stretched to fill the background of the login page.&#039;;                 &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have a new setting that lets us upload a file - but it doesn&#039;t actually do anything yet. We need to update the theme to set this image background on the login page.&lt;br /&gt;
&lt;br /&gt;
In order to change the SCSS for our theme we will add 2 additional SCSS files and include them before and after our main scss.&lt;br /&gt;
&lt;br /&gt;
We already have a function in our lib.php file which fetches the main SCSS for our theme. This is a good point to include additional SCSS files. We can add 2 lines to the end of this function to achieve this.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        // This preset file was fetched from the file area for theme_photo and not theme_boost (see the line above).                &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Pre CSS - this is loaded AFTER any prescss from the setting but before the main scss.                                        &lt;br /&gt;
    $pre = file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/photo/scss/pre.scss&#039;);                                                         &lt;br /&gt;
    // Post CSS - this is loaded AFTER the main scss but before the extra scss from the setting.                                    &lt;br /&gt;
    $post = file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/photo/scss/post.scss&#039;);                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Combine them together.                                                                                                       &lt;br /&gt;
    return $pre . &amp;quot;\n&amp;quot; . $scss . &amp;quot;\n&amp;quot; . $post;                                                                                      &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;scss/pre.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
// Pre SCSS for the theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;scss/post.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
// Post SCSS for the theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Why do we use pre and post SCSS? ====&lt;br /&gt;
SCSS/SASS is a powerful language for creating CSS. It supports variables, functions, loops just like php. For lots of information and an introduction to SCSS read about [https://en.wikipedia.org/wiki/Sass_(stylesheet_language) Sass on wikipedia]. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pre SCSS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In Boost we use many variables when creating style rules.&lt;br /&gt;
&lt;br /&gt;
When declaring a variable in SCSS - it is best practice to define it like this:&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
$mycoolcolour: #FF0 !default;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this means is - if this variable is not defined already - set it to the hex value &#039;#FF0&#039;;&lt;br /&gt;
&lt;br /&gt;
So by setting this variable in some PRE scss we can override the default value of this variable everywhere it is used. Boost is built with the [https://v4-alpha.getbootstrap.com/ Bootstrap 4 (Alpha 4)] CSS Framework. This is a framework which uses SCSS to provide many extremely useful layouts and components which can be reused without adding specific CSS rules to style every page. Because bootstrap consistently uses variables we can customise many of these components easily by setting the value of the variables before we include the Bootstrap SCSS files.&lt;br /&gt;
&lt;br /&gt;
Many variables are available in /theme/boost/scss/bootstrap/_variables.scss - as an example we can change the look of all buttons and input fields with this one variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
$border-radius: 8px;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Post SCSS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Post SCSS is useful for defining full CSS rules. Because they are included last, they override any previous matching selector with the same [https://en.wikipedia.org/wiki/Cascading_Style_Sheets#Specificity Specificity].&lt;br /&gt;
&lt;br /&gt;
=== Tips for customising Moodle with SCSS (or CSS) ===&lt;br /&gt;
Some handy things to know when you are new to theming is that Moodle adds some classes to every page that helps you target a specific page or set of pages with some style rules. &lt;br /&gt;
&lt;br /&gt;
If you inspect a moodle page and look at the body tag you will see a long list of classes e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code html&amp;gt;&lt;br /&gt;
&amp;lt;body id=&amp;quot;page-course-view-weeks&amp;quot; class=&amp;quot;format-weeks  path-course path-course-view safari dir-ltr lang-en yui-skin-sam yui3-skin-sam damyon-per-in-moodle-com--stable_master pagelayout-course course-11 context-497 category-1 drawer-open-left jsenabled&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can see from this example that each page gets an id. This is a simplified representation of the current page in the navigation. In this example we are looking at the course page and this course is using the weeks format. &lt;br /&gt;
&lt;br /&gt;
The classes on the body tag can also be used to target a page or set of pages.&lt;br /&gt;
* &amp;lt;code&amp;gt;format-weeks&amp;lt;/code&amp;gt; The course format&lt;br /&gt;
* &amp;lt;code&amp;gt;path-course path-course-view&amp;lt;/code&amp;gt; The parts of the bread-crumb leading up to the current page (The current page is what goes in the id)&lt;br /&gt;
* &amp;lt;code&amp;gt;safari&amp;lt;/code&amp;gt; Some server side guessing of the browser type - it&#039;s not accurate so I would not rely on it&lt;br /&gt;
* &amp;lt;code&amp;gt;dir-ltr&amp;lt;/code&amp;gt; The direction of the current language for the page ( dir-rtl for RTL languages )&lt;br /&gt;
* &amp;lt;code&amp;gt;lang-en&amp;lt;/code&amp;gt; The current language of the page&lt;br /&gt;
* &amp;lt;code&amp;gt;yui*&amp;lt;/code&amp;gt; Legacy yui classes - ignore these&lt;br /&gt;
* &amp;lt;code&amp;gt;damyon-per-in-moodle-com--stable_master&amp;lt;/code&amp;gt; The current hostname for the site + the site name&lt;br /&gt;
* &amp;lt;code&amp;gt;pagelayout-course&amp;lt;/code&amp;gt; The layout type for the current page&lt;br /&gt;
* &amp;lt;code&amp;gt;course-11&amp;lt;/code&amp;gt; The id of the current course&lt;br /&gt;
* &amp;lt;code&amp;gt;context-497&amp;lt;/code&amp;gt; The current context id&lt;br /&gt;
* &amp;lt;code&amp;gt;category-1&amp;lt;/code&amp;gt; The category for the current course&lt;br /&gt;
* &amp;lt;code&amp;gt;drawer-open-left&amp;lt;/code&amp;gt; Added / removed when the navigation drawer is opened / closed in Boost&lt;br /&gt;
* &amp;lt;code&amp;gt;jsenabled&amp;lt;/code&amp;gt; True if the browser supports javascript&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/dev/Themes_overview#.3Cbody.3E_CSS_id_and_classes Read about Body id and classes].&lt;br /&gt;
&lt;br /&gt;
In our example the page layout is the most useful here as we have a specific page layout for login pages. We can now craft a rule that applies a background image only to login pages using &amp;quot;body.pagelayout-login&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How do we refer to an image in SCSS ? ===&lt;br /&gt;
So now we can add a rule to the post.scss which will set the background image for the login page. First we need to know how to construct a url to the background images from our stylesheet. &lt;br /&gt;
&lt;br /&gt;
In stylesheets in Moodle we can use a special pix tag to refer to images from our theme. The rule to attach the background image looks like this:&lt;br /&gt;
&#039;&#039;scss/post.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
body.pagelayout-login {                                                                                                             &lt;br /&gt;
    background-image: url([[pix:theme_photo|loginbackgroundimage]]);                                                                &lt;br /&gt;
    background-size: cover;                                                                                                         &lt;br /&gt;
}                          &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are 2 important parts to this tag (the bit in square brackets). The first is &amp;quot;theme_photo&amp;quot;. In this case we are passing a component name, the image serving code in theme_config::resolve_image_location() will then look for an image file in several locations. One of these is in &amp;quot;$CFG-&amp;gt;dataroot/pix_plugins/$type/$plugin/$image&amp;quot;. We can use this to make sure the image gets served correctly by copying the file saved in the setting to this location every time it is updated. (There is an alterative way we could do this by implementing pluginfile.php in our theme - which you can read about in the [[File API]] ).&lt;br /&gt;
&lt;br /&gt;
If we had just passed the value &amp;quot;theme&amp;quot; the image serving code would have looked for the image in the &amp;quot;pix&amp;quot; folder of our theme.&lt;br /&gt;
&lt;br /&gt;
So - we need this final change to copy the image file into our dataroot each time the setting is changed.&lt;br /&gt;
&lt;br /&gt;
In the settings file we will update the callback to a new function which we will define in our lib.php.&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Login page background setting.                                                                                               &lt;br /&gt;
    // We use variables for readability.                                                                                            &lt;br /&gt;
    $name = &#039;theme_photo/loginbackgroundimage&#039;;                                                                                     &lt;br /&gt;
    $title = get_string(&#039;loginbackgroundimage&#039;, &#039;theme_photo&#039;);                                                                     &lt;br /&gt;
    $description = get_string(&#039;loginbackgroundimage_desc&#039;, &#039;theme_photo&#039;);                                                          &lt;br /&gt;
    // This creates the new setting.                                                                                                &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;loginbackgroundimage&#039;);                             &lt;br /&gt;
    // This function will copy the image into the data_root location it can be served from.                                         &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_photo_update_settings_images&#039;);                                                            &lt;br /&gt;
    // We always have to add the setting to a page for it to have any effect.                                                       &lt;br /&gt;
    $page-&amp;gt;add($setting);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_update_settings_images($settingname) {                                                                         &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // The setting name that was updated comes as a string like &#039;s_theme_photo_loginbackgroundimage&#039;.                               &lt;br /&gt;
    // We split it on &#039;_&#039; characters.                                                                                               &lt;br /&gt;
    $parts = explode(&#039;_&#039;, $settingname);                                                                                            &lt;br /&gt;
    // And get the last one to get the setting name..                                                                               &lt;br /&gt;
    $settingname = end($parts);                                                                                                     &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Admin settings are stored in system context.                                                                                 &lt;br /&gt;
    $syscontext = context_system::instance();                                                                                       &lt;br /&gt;
    // This is the component name the setting is stored in.                                                                         &lt;br /&gt;
    $component = &#039;theme_photo&#039;;                                                                                                     &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // This is the value of the admin setting which is the filename of the uploaded file.                                           &lt;br /&gt;
    $filename = get_config($component, $settingname);                                                                               &lt;br /&gt;
    // We extract the file extension because we want to preserve it.                                                                &lt;br /&gt;
    $extension = substr($filename, strrpos($filename, &#039;.&#039;) + 1);                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // This is the path in the moodle internal file system.                                                                         &lt;br /&gt;
    $fullpath = &amp;quot;/{$syscontext-&amp;gt;id}/{$component}/{$settingname}/0{$filename}&amp;quot;;                                                      &lt;br /&gt;
    // Get an instance of the moodle file storage.                                                                                  &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
    // This is an efficient way to get a file if we know the exact path.                                                            &lt;br /&gt;
    if ($file = $fs-&amp;gt;get_file_by_hash(sha1($fullpath))) {                                                                           &lt;br /&gt;
        // We got the stored file - copy it to dataroot.                                                                            &lt;br /&gt;
        // This location matches the searched for location in theme_config::resolve_image_location.                                 &lt;br /&gt;
        $pathname = $CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039; . $settingname . &#039;.&#039; . $extension;                                 &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // This pattern matches any previous files with maybe different file extensions.                                            &lt;br /&gt;
        $pathpattern = $CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039; . $settingname . &#039;.*&#039;;                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Make sure this dir exists.                                                                                               &lt;br /&gt;
        @mkdir($CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039;, $CFG-&amp;gt;directorypermissions, true);                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Delete any existing files for this setting.                                                                              &lt;br /&gt;
        foreach (glob($pathpattern) as $filename) {                                                                                 &lt;br /&gt;
            @unlink($filename);                                                                                                     &lt;br /&gt;
        }                                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Copy the current file to this location.                                                                                  &lt;br /&gt;
        $file-&amp;gt;copy_content_to($pathname);                                                                                          &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Reset theme caches.                                                                                                          &lt;br /&gt;
    theme_reset_all_caches();                                                                                                       &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, create an image called &#039;&#039;&#039;loginbackgroundimage&#039;&#039;&#039; and upload it to &#039;&#039;&#039;/theme/photo/pix&#039;&#039;&#039;. You will be able to view the image in the background of your login page. &lt;br /&gt;
&lt;br /&gt;
It is now easy to add a new background image setting for every layout type. I can re-use this theme_photo_update_settings_images callback for each one - so all I have to do is add the setting to the settings.php file, add the SCSS rule to the scss/post.scss file and add the lang strings to the language file.&lt;br /&gt;
&lt;br /&gt;
Thats it for this tutorial, but there are [[:Category:Themes| more Themes docs]] to browse.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Themes]]&lt;/div&gt;</summary>
		<author><name>Meeth</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=57689</id>
		<title>Blocks</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=57689"/>
		<updated>2020-07-08T09:10:01Z</updated>

		<summary type="html">&lt;p&gt;Meeth: /* I Just Hear Static */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039; A Step-by-step Guide To Creating Blocks &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Original Author: Jon Papaioannou ([mailto:pj@moodle.org pj@moodle.org])&lt;br /&gt;
&lt;br /&gt;
Updated to Moodle 2.0 and above by: Greg J Preece ([mailto:greg.preece@blackboard.com greg.preece@blackboard.com])&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
The present document serves as a guide to developers who want to create their own blocks for use in Moodle. It applies to the 2.0 development version of Moodle (and any newer) &#039;&#039;&#039;only&#039;&#039;&#039;, as the blocks API changed significantly enough to warrant new documentation. Those wishing to read the old tutorial for Moodles 1.5 to 1.9 can find it under [[Blocks/Blocks for 1.5 to 1.9| Blocks for 1.5 to 1.9]].&lt;br /&gt;
&lt;br /&gt;
The guide is written as an interactive course which aims to develop a configurable, multi-purpose block that displays arbitrary HTML. It&#039;s targeted mainly at people with little experience with Moodle or programming in general and aims to show how easy it is to create new blocks for Moodle. A certain small amount of PHP programming knowledge is still required, though. &lt;br /&gt;
&lt;br /&gt;
Experienced developers and those who just want a &#039;&#039;&#039;programmer&#039;s reference&#039;&#039;&#039; text should refer to [[Blocks/Appendix_A| Appendix A]] because the main guide has a rather low concentration of pure information in the text.&lt;br /&gt;
&lt;br /&gt;
== Basic Concepts ==&lt;br /&gt;
&lt;br /&gt;
Through this guide, we will be following the creation of an &amp;quot;HTML&amp;quot; block from scratch in order to demonstrate most of the block features at our disposal. Our block will be named &amp;quot;SimpleHTML&amp;quot;. This does not constrain us regarding the name of the actual directory on the server where the files for our block will be stored, but for consistency we will follow the practice of using the lowercased form &amp;quot;simplehtml&amp;quot; in any case where such a name is required. &lt;br /&gt;
&lt;br /&gt;
Whenever we refer to a file or directory name which contains &amp;quot;simplehtml&amp;quot;, it&#039;s important to remember that &#039;&#039;only&#039;&#039; the &amp;quot;simplehtml&amp;quot; part is up to us to change; the rest is standardised and essential for Moodle to work correctly.&lt;br /&gt;
&lt;br /&gt;
Whenever a file&#039;s path is mentioned in this guide, it will always start with a slash. This refers to the Moodle home directory; all files and directories will be referred to with respect to that directory.&lt;br /&gt;
&lt;br /&gt;
== Ready, Set, Go! ==&lt;br /&gt;
&lt;br /&gt;
To define a &amp;quot;block&amp;quot; in Moodle, in the most basic case we need to provide just four PHP files. Remember, in this example we are creating a block called &#039;simplehtml&#039;, replace &#039;simplehtml&#039; with the name of your custom block. The four files should be located in blocks/simplehtml and are:&lt;br /&gt;
&lt;br /&gt;
=== block_simplehtml.php ===&lt;br /&gt;
&lt;br /&gt;
This file will hold the class definition for the block, and is used both to manage it as a plugin and to render it onscreen.&lt;br /&gt;
&lt;br /&gt;
We start by creating the main object file, &#039;block_simplehtml.php&#039;. We then begin coding the block:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
class block_simplehtml extends block_base {&lt;br /&gt;
    public function init() {&lt;br /&gt;
        $this-&amp;gt;title = get_string(&#039;simplehtml&#039;, &#039;block_simplehtml&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    // The PHP tag and the curly bracket for the class definition &lt;br /&gt;
    // will only be closed after there is another function added in the next section.&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first line is our block class definition; it must be named exactly in the manner shown. Again, only the &amp;quot;simplehtml&amp;quot; part can (and indeed must) change; everything else is standardised.&lt;br /&gt;
&lt;br /&gt;
Our class is then given a small method: [[Blocks/Appendix_A#init.28.29| init()]]. This is essential for all blocks, and its purpose is to give values to any class member variables that need instantiating. &lt;br /&gt;
&lt;br /&gt;
In this very basic example, we only want to set [[Blocks/Appendix_A#.24this-.3Etitle| $this-&amp;gt;title]], which is the title displayed in the header of our block. We can set it to whatever we like; in this case it&#039;s set to read the actual title from the language file mentioned below, which is then distributed along with the block. I&#039;ll skip ahead a bit here and say that if you want your block to display &#039;&#039;&#039;no&#039;&#039;&#039; title at all, then you should set this to any descriptive value you want (but &#039;&#039;&#039;not&#039;&#039;&#039; make it an empty string). We will later see [[Blocks#Eye_Candy|how to disable the title&#039;s display]].&lt;br /&gt;
&lt;br /&gt;
=== db/access.php ===&lt;br /&gt;
&lt;br /&gt;
This file will hold the new capabilities created by the block.&lt;br /&gt;
&lt;br /&gt;
Moodle 2.4 onwards introduced the capabilities addinstance and myaddinstance for core blocks. They were introduced so that it was possible to control the use of individual blocks. These capabilities should also be added to your custom block, so in this case to the file blocks/simplehtml/db/access.php. If your block is not going to be used in the &#039;My Moodle page&#039; (ie, your applicable_formats function (discussed later) has &#039;my&#039; set to false.) then the myaddinstance capability does not need to be given to any user, but it must still be defined here otherwise you will get errors on certain pages. The following is the capabilities array and how it should look for any new blocks.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
    $capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;block/simplehtml:myaddinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_SYSTEM,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;user&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/my:manageblocks&#039;&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    &#039;block/simplehtml:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_SPAM | RISK_XSS,&lt;br /&gt;
&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_BLOCK,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/site:manageblocks&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== lang/en/block_simplehtml.php ===&lt;br /&gt;
&lt;br /&gt;
This is the English language file for your block. If you are not an English speaker, you can replace &#039;en&#039; with your appropriate language code (but even then you will need english folder !). All language files for blocks go under the /lang subfolder of the block&#039;s installation folder.&lt;br /&gt;
&lt;br /&gt;
Moodle 2.0 and above require a name for our plugin to show in the upgrading page. We set this value, along with the capabilities we created and any other language strings we wish to use within the block, in a language package as previously mentioned (the same file where we put our string for the plugin title).&lt;br /&gt;
&lt;br /&gt;
The capabilities added above need descriptions for pages that allow setting of capabilities. These should also be added to the language file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Simple HTML block&#039;;&lt;br /&gt;
$string[&#039;simplehtml&#039;] = &#039;Simple HTML&#039;;&lt;br /&gt;
$string[&#039;simplehtml:addinstance&#039;] = &#039;Add a new simple HTML block&#039;;&lt;br /&gt;
$string[&#039;simplehtml:myaddinstance&#039;] = &#039;Add a new simple HTML block to the My Moodle page&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
This file will hold version information for the plugin, along &#039;&#039;&#039;with other advanced parameters&#039;&#039;&#039; (not covered here - see [[version.php]] if you want &#039;&#039;&#039;more details&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Prior to Moodle 2.0, version details for blocks were stored as class fields; as of Moodle 2.0 these are stored in a file called version.php, stored under &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;version.php&#039;&#039;&#039;&#039;&#039;. The version file is very simple indeed, containing only a few field definitions, depending on your needs. Here is an example:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
$plugin-&amp;gt;component = &#039;block_simplehtml&#039;;  // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494)&lt;br /&gt;
$plugin-&amp;gt;version = 2011062800;  // YYYYMMDDHH (year, month, day, 24-hr time)&lt;br /&gt;
$plugin-&amp;gt;requires = 2010112400; // YYYYMMDDHH (This is the release version for Moodle 2.0)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This file contains object field definitions that denote the full [[Frankenstyle|frankenstyle]] component name in the form of &#039;&#039;plugintype_pluginname&#039;&#039; and the version number of the block, along with the minimum version of Moodle that must be installed in order to use it. Please note that the object being used here is &#039;&#039;always&#039;&#039; called &#039;&#039;&#039;$plugin&#039;&#039;&#039;, and that you do not need to create this object yourself within the version file. Note also we don&#039;t include a closing &amp;quot;?&amp;gt;&amp;quot; tag. This is intentional, and a [[Coding_style#PHP_tags | workaround for whitespace issues]].&lt;br /&gt;
&lt;br /&gt;
The exact Moodle version of a release can be found in [[Releases]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== I Just Hear Static ==&lt;br /&gt;
In order to get our block to actually display something on screen, we need to add one more method to our class (before the final closing brace in our file) inside of the block_simplehtml.php script. The new code is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;  &lt;br /&gt;
  public function get_content() {&lt;br /&gt;
    if ($this-&amp;gt;content !== null) {&lt;br /&gt;
      return $this-&amp;gt;content;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $this-&amp;gt;content         =  new stdClass;&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text   = &#039;The content of our SimpleHTML block!&#039;;&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;footer = &#039;Footer here...&#039;;&lt;br /&gt;
 &lt;br /&gt;
    return $this-&amp;gt;content;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Add your block to the front page!&#039;&#039;&#039;&lt;br /&gt;
Don&#039;t forget (especially if you&#039;re a new Moodle user) to add your block to the front page. Turn Editing On, and add your block to the page.&lt;br /&gt;
&lt;br /&gt;
It can&#039;t get any simpler than that, can it? Let&#039;s dissect this method to see what&#039;s going on...&lt;br /&gt;
&lt;br /&gt;
First of all, there is a check that returns the current value of [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]] if it&#039;s not NULL; otherwise we proceed with &amp;quot;computing&amp;quot; it. Since the computation is potentially a time-consuming operation and it &#039;&#039;&#039;will&#039;&#039;&#039; be called several times for each block (Moodle works that way internally), we take a precaution and include this time-saver.&lt;br /&gt;
Supposing the content had not been computed before (it was NULL), we then define it from scratch. The code speaks for itself there, so there isn&#039;t much to say. Just keep in mind that we can use HTML both in the text &#039;&#039;&#039;and&#039;&#039;&#039; in the footer, if we want to.&lt;br /&gt;
&lt;br /&gt;
It&#039;s worth mentioning that this is not the only type of content a block can output. You can also create lists and hierarchical trees, which are better suited for certain types of output, such as menus. These different content types have an impact on the content object and how it is constructed. For more information, see [[Blocks/Appendix A#.24this-.3Econtent_type|Appendix A]]&lt;br /&gt;
&lt;br /&gt;
At this point our block should be capable of being automatically installed in Moodle and added to courses; visit your administration page to install it (Click &amp;quot;Notifications&amp;quot; under the Site Administration Block) and after seeing it in action come back to continue our tutorial.&lt;br /&gt;
&lt;br /&gt;
== Configure That Out ==&lt;br /&gt;
&lt;br /&gt;
The current version of our block doesn&#039;t really do much; it just displays a fixed message, which is not very useful. What we&#039;d really like to do is allow the teachers to customize what goes into the block. This, in block-speak, is called &amp;quot;instance configuration&amp;quot;. Basic instance configuration is automatic in Moodle 2.0; if you put any page with blocks on it into &amp;quot;editing mode&amp;quot;, you will notice that each block has an edit button in its title bar. Clicking on this will take you to the block configuration form. The settings that Moodle adds to this form by default relate to the block&#039;s appearance and position on Moodle pages. &lt;br /&gt;
&lt;br /&gt;
We can extend this configuration form, and add custom preferences fields, so that users can better tailor our block to a given task or page. To extend the configuration form, create the file &amp;lt;span class=&amp;quot;filename&amp;quot;&amp;gt;/blocks/simplehtml/&#039;&#039;&#039;edit_form.php&#039;&#039;&#039;&amp;lt;/span&amp;gt;, and fill it with the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class block_simplehtml_edit_form extends block_edit_form {&lt;br /&gt;
        &lt;br /&gt;
    protected function specific_definition($mform) {&lt;br /&gt;
        &lt;br /&gt;
        // Section header title according to language file.&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;header&#039;, &#039;config_header&#039;, get_string(&#039;blocksettings&#039;, &#039;block&#039;));&lt;br /&gt;
&lt;br /&gt;
        // A sample string variable with a default value.&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;config_text&#039;, get_string(&#039;blockstring&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;config_text&#039;, &#039;default value&#039;);&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;config_text&#039;, PARAM_RAW);        &lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The first line declares a class that inherits &#039;&#039;&#039;from block_edit_form&#039;&#039;&#039;, and this allows Moodle to identify the code to execute in the configuration page. The &#039;&#039;&#039;specific_definition()&#039;&#039;&#039; method is where your form elements are defined, and these take the same format as with the standard [[lib/formslib.php_Form_Definition|Moodle form library]].  Within our specific_definition method, we have created a header, and an input field which will accept text to be used within the block. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; You might want extend language file for your block (lang/en/block_simplehtml.php) and add a value for &amp;quot;blockstring&amp;quot; defined in a code above.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;IMPORTANT:&#039;&#039;&#039; All your field names need to start with &amp;quot;config_&amp;quot;, otherwise they will not be saved and will not be available within the block via [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]]. &lt;br /&gt;
&lt;br /&gt;
So once our instance configuration form has been saved, we can use the inputted text within the block like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (! empty($this-&amp;gt;config-&amp;gt;text)) {&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text = $this-&amp;gt;config-&amp;gt;text;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] is available in all block methods &#039;&#039;except&#039;&#039; [[Blocks/Appendix_A#init.28.29|init()]]. This is because [[Blocks/Appendix_A#init.28.29|init()]] is called immediately as the block is being created, with the purpose of setting things up, so [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] has not yet been instantiated.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note about Checkbox:&#039;&#039;&#039; You cannot use the &#039;checkbox&#039; element in the form (once set it will stay set). You must use advcheckbox instead. &lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== The Specialists ==&lt;br /&gt;
&lt;br /&gt;
Implementing instance configuration for the block&#039;s contents was good enough to whet our appetite, but who wants to stop there? Why not customize the block&#039;s title, too?&lt;br /&gt;
&lt;br /&gt;
Why not, indeed. Well, our first attempt to achieve this is natural enough: let&#039;s add another field to &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;edit_form.php&#039;&#039;&#039;&#039;&#039;. Here goes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    // A sample string variable with a default value.&lt;br /&gt;
    $mform-&amp;gt;addElement(&#039;text&#039;, &#039;config_title&#039;, get_string(&#039;blocktitle&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
    $mform-&amp;gt;setDefault(&#039;config_title&#039;, &#039;default value&#039;);&lt;br /&gt;
    $mform-&amp;gt;setType(&#039;config_title&#039;, PARAM_TEXT);        &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We save the edited file, go to a course, edit the title of the block and... nothing happens! The instance configuration is saved correctly, all right (editing it once more proves that) but it&#039;s not being displayed. All we get is just the simple &amp;quot;SimpleHTML&amp;quot; title.&lt;br /&gt;
&lt;br /&gt;
That&#039;s not too weird, if we think back a bit. Do you remember that [[Blocks/Appendix_A#init.28.29|init()]] method, where we set [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]]? We didn&#039;t actually change its value from then, and [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]] is definitely not the same as &#039;&#039;&#039;$this-&amp;gt;config-&amp;gt;title&#039;&#039;&#039; (to Moodle, at least). What we need is a way to update [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]] with the value in the instance configuration. But as we said a bit earlier, we can use [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] in all methods &#039;&#039;except&#039;&#039; [[Blocks/Appendix_A#init.28.29|init()]]! So what can we do?&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pull out another ace from our sleeve, and add this small method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function specialization() {&lt;br /&gt;
    if (isset($this-&amp;gt;config)) {&lt;br /&gt;
        if (empty($this-&amp;gt;config-&amp;gt;title)) {&lt;br /&gt;
            $this-&amp;gt;title = get_string(&#039;defaulttitle&#039;, &#039;block_simplehtml&#039;);            &lt;br /&gt;
        } else {&lt;br /&gt;
            $this-&amp;gt;title = $this-&amp;gt;config-&amp;gt;title;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (empty($this-&amp;gt;config-&amp;gt;text)) {&lt;br /&gt;
            $this-&amp;gt;config-&amp;gt;text = get_string(&#039;defaulttext&#039;, &#039;block_simplehtml&#039;);&lt;br /&gt;
        }    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aha, here&#039;s what we wanted to do all along! But what&#039;s going on with the [[Blocks/Appendix_A#specialization.28.29| specialization()]] method?&lt;br /&gt;
&lt;br /&gt;
This &amp;quot;magic&amp;quot; method has actually a very nice property: it&#039;s &#039;&#039;guaranteed&#039;&#039; to be automatically called by Moodle as soon as our instance configuration is loaded and available (that is, immediately after [[Blocks/Appendix_A#init.28.29|init()]] is called). That means before the block&#039;s content is computed for the first time, and indeed before &#039;&#039;anything&#039;&#039; else is done with the block. Thus, providing a [[Blocks/Appendix_A#specialization.28.29| specialization()]] method is the natural choice for any configuration data that needs to be acted upon or made available &amp;quot;as soon as possible&amp;quot;, as in this case.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Now You See Me, Now You Don&#039;t ==&lt;br /&gt;
&lt;br /&gt;
Now would be a good time to mention another nifty technique that can be used in blocks, and which comes in handy quite often. Specifically, it may be the case that our block will have something interesting to display some of the time; but in some other cases, it won&#039;t have anything useful to say. An example here would be the &amp;quot;Recent Activity&amp;quot; block, in the case where no recent activity in fact exists. &lt;br /&gt;
&lt;br /&gt;
However in that case the block chooses to explicitly inform you of the lack of said activity, which is arguably useful. It would be nice, then, to be able to have our block &amp;quot;disappear&amp;quot; if it&#039;s not needed to display it.&lt;br /&gt;
&lt;br /&gt;
This is indeed possible, and the way to do it is to make sure that after the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method is called, the block has no content to display. This means that all fields in $this-&amp;gt;content should be equal to the empty string (&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;). In the case of our HTML-based block, these fields are $this-&amp;gt;content-&amp;gt;text and $this-&amp;gt;content-&amp;gt;footer. Moodle performs this check by calling the block&#039;s [[Blocks/Appendix_A#is_empty.28.29| is_empty()]] method, and if the block is indeed empty then it is not displayed at all.&lt;br /&gt;
&lt;br /&gt;
Note that the exact value of the block&#039;s title and the presence or absence of a [[Blocks/Appendix_A#hide_header.28.29| hide_header()]] method do &#039;&#039;not&#039;&#039; affect this behavior. A block is considered empty if it has no content, irrespective of anything else.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== We Are Legion ==&lt;br /&gt;
&lt;br /&gt;
Right now our block is fully configurable, both in title and content. It&#039;s so versatile, in fact, that we could make pretty much anything out of it. It would be really nice to be able to add multiple blocks of this type to a single course. And, as you might have guessed, doing that is as simple as adding another small method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_allow_multiple() {&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells Moodle that it should allow any number of instances of the SimpleHTML block in any course. After saving the changes to our file, Moodle immediately allows us to add multiple copies of the block without further ado!&lt;br /&gt;
&lt;br /&gt;
Please note that even if a block itself allows multiple instances in the same page, the administrator still has the option of disallowing such behavior. This setting can be set separately for each block from the Administration / Configuration / Blocks page.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== The Effects of Globalization ==&lt;br /&gt;
&lt;br /&gt;
Configuring each block instance with its own personal data is cool enough, but sometimes administrators need some way to &amp;quot;touch&amp;quot; all instances of a specific block at the same time. In the case of our SimpleHTML block, a few settings that would make sense to apply to all instances aren&#039;t that hard to come up with. &lt;br /&gt;
&lt;br /&gt;
For example, we might want to limit the contents of each block to only so many characters, or we might have a setting that filters HTML out of the block&#039;s contents, only allowing pure text in. Granted, such a feature wouldn&#039;t win us any awards for naming our block &amp;quot;SimpleHTML&amp;quot; but some tormented administrator somewhere might actually find it useful.&lt;br /&gt;
&lt;br /&gt;
This kind of configuration is called &amp;quot;global configuration&amp;quot; and applies only to a specific block type (all instances of that block type are affected, however).  Implementing such configuration for our block is quite similar to implementing the instance configuration. We will now see how to implement the second example, having a setting that only allows text and not HTML in the block&#039;s contents. To enable global configuration for the block, we create a new file, &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;settings.php&#039;&#039;&#039;&#039;&#039;, and populate it with form field definitions for each setting, which Moodle will use to generate and handle a global settings form.  This is quite similar in concept to how we generated the instance configuration form earlier, but the actual code used to generate the form and fields is somewhat different.&lt;br /&gt;
&lt;br /&gt;
Place the following in your settings.php file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
$settings-&amp;gt;add(new admin_setting_heading(&lt;br /&gt;
            &#039;headerconfig&#039;,&lt;br /&gt;
            get_string(&#039;headerconfig&#039;, &#039;block_simplehtml&#039;),&lt;br /&gt;
            get_string(&#039;descconfig&#039;, &#039;block_simplehtml&#039;)&lt;br /&gt;
        ));&lt;br /&gt;
&lt;br /&gt;
$settings-&amp;gt;add(new admin_setting_configcheckbox(&lt;br /&gt;
            &#039;simplehtml/Allow_HTML&#039;,&lt;br /&gt;
            get_string(&#039;labelallowhtml&#039;, &#039;block_simplehtml&#039;),&lt;br /&gt;
            get_string(&#039;descallowhtml&#039;, &#039;block_simplehtml&#039;),&lt;br /&gt;
            &#039;0&#039;&lt;br /&gt;
        ));    &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, to generate a global configuration form, we simply create admin setting objects and add them to an array. This array is then stepped over to create the settings form, and the inputted data is automatically saved to the database. Full details of the setting types available and how to add them can be found under [[Admin_settings#Individual_settings]].&lt;br /&gt;
&lt;br /&gt;
We&#039;ve now created a header and checkbox form element to accept configuration details from the site admin. You should pay extra attention to the name of our checkbox element, &#039;&#039;&#039; &#039;simplehtml/Allow_HTML&#039; &#039;&#039;&#039;, as it specifies not only the name of the configuration option, but also how it should be stored. If you simply specify a name for the config option, it will be stored in the global $CFG object, and in the &#039;&#039;&amp;lt;prefix&amp;gt;_config&#039;&#039; database table. This will make your config variable available immediately via $CFG without requiring an additional database call, but will also increase the size of the $CFG object. In addition, we must prefix the variable with the name of our block, otherwise we run the risk of our config variable sharing its name with a similar variable in another plugin, or within Moodle itself.&lt;br /&gt;
&lt;br /&gt;
The preferred method of storing your block&#039;s configuration data is to prefix each config variable name in your settings.php file with your block&#039;s name, followed by a slash ( / ), and the name of the configuration variable, as we have done above. If you write your settings.php file in this way, then your variables will be stored in the &#039;&#039;&amp;lt;prefix&amp;gt;_config_plugin&#039;&#039; table, under your block&#039;s name. Your config data will still be available via a &#039;&#039;&#039;get_config()&#039;&#039;&#039; call, and name collision will be impossible between plugins.&lt;br /&gt;
&lt;br /&gt;
Finally, if you&#039;re wondering why there are two language tags specified for each element, the first tag is for the element&#039;s label or primary text, and the second tag is for its description. And that&#039;s it. Pretty easy, huh?&lt;br /&gt;
&lt;br /&gt;
=== Enabling Global Configuration ===&lt;br /&gt;
{{Moodle 2.4}}Since version 2.4, the following line must be added to the /blocks/simplehtml/block_simplehtml.php file in order to enable global configuration:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    function has_config() {return true;}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This line tells Moodle that the block has a settings.php file.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE FOR UPGRADERS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You&#039;ll notice that the settings.php file and parsed element names replaces Moodle&#039;s old storage method, wherein it would send all the configuration data to your block&#039;s [[Blocks/Appendix_A#config_save.28.29|config_save()]] method, and allow you to override how the data is saved. The [[Blocks/Appendix_A#config_save.28.29|config_save()]] method is no longer used in Moodle 2.x; however the [[Blocks/Appendix_A#instance_config_save.28.29|instance_config_save()]] method is very much alive and well, as you will see shortly.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
=== Accessing Global Config Data  ===&lt;br /&gt;
&lt;br /&gt;
Now that we have global data defined for the plugin, we need to know how to access it within our code.  If you saved your config variables in the global namespace, you can access them from the global $CFG object, like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$allowHTML = $CFG-&amp;gt;Allow_HTML;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If, as recommended, you saved your config variables in a custom namespace for your block, then you can access them via a call to &#039;&#039;&#039;get_config()&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$allowHTML = get_config(&#039;simplehtml&#039;, &#039;Allow_HTML&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
=== Rolling It All Together ===&lt;br /&gt;
&lt;br /&gt;
OK, so we now have an instance configuration form that allows users to enter custom content text for a block, and a global configuration option that dictates whether or not that user should be allowed to enter HTML tags as part of the content. Now we just need to tie the two together. But if Moodle takes care of the form processing for our instance configuration in edit_form.php, how can we capture it and remove the HTML tags where required?&lt;br /&gt;
&lt;br /&gt;
Well, fortunately, there is a way this can be done.  By overriding the [[Blocks/Appendix_A#instance_config_save.28.29| instance_config_save()]] method in our block class, we can modify the way in which instance configuration data is stored after input. The default implementation is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_config_save($data, $nolongerused = false) {&lt;br /&gt;
  $data = stripslashes_recursive($data);&lt;br /&gt;
  $this-&amp;gt;config = $data;&lt;br /&gt;
  return set_field(&#039;block_instance&#039;, &lt;br /&gt;
                   &#039;configdata&#039;,&lt;br /&gt;
                    base64_encode(serialize($data)),&lt;br /&gt;
                   &#039;id&#039;, &lt;br /&gt;
                   $this-&amp;gt;instance-&amp;gt;id);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This may look intimidating at first (what&#039;s all this stripslashes_recursive() and base64_encode() and serialize() stuff?) but do not despair; we won&#039;t have to touch any of it. We will only add some extra validation code in the beginning and then instruct Moodle to additionally call this default implementation to do the actual storing of the data. Specifically, we will add a method to our class which goes like this:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_config_save($data,$nolongerused =false) {&lt;br /&gt;
  if(get_config(&#039;simplehtml&#039;, &#039;Allow_HTML&#039;) == &#039;1&#039;) {&lt;br /&gt;
    $data-&amp;gt;text = strip_tags($data-&amp;gt;text);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // And now forward to the default implementation defined in the parent class&lt;br /&gt;
  return parent::instance_config_save($data,$nolongerused);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(This example assumes you are using a custom namespace for the block.)&lt;br /&gt;
&lt;br /&gt;
At last! Now the administrator has absolute power of life and death over what type of content is allowed in our &amp;quot;SimpleHTML&amp;quot; block! Absolute? Well... not exactly. In fact, if we think about it for a while, it will become apparent that if at some point in time HTML is allowed and some blocks have saved their content with HTML included, and afterwards the administrator changes the setting to &amp;quot;off&amp;quot;, this will only prevent subsequent content changes from including HTML. Blocks which already had HTML in their content would continue to display it!&lt;br /&gt;
&lt;br /&gt;
Following that train of thought, the next stop is realizing that we wouldn&#039;t have this problem if we had chosen the lazy approach a while back, because in that case we would &amp;quot;sanitize&amp;quot; each block&#039;s content just before it was displayed. &lt;br /&gt;
&lt;br /&gt;
The only thing we can do with the eager approach is strip all the tags from the content of all SimpleHTML instances as soon as the admin setting is changed to &amp;quot;HTML off&amp;quot;; but even then, turning the setting back to &amp;quot;HTML on&amp;quot; won&#039;t bring back the tags we stripped away. On the other hand, the lazy approach might be slower, but it&#039;s more versatile; we can choose whether to strip or keep the HTML before displaying the content, and we won&#039;t lose it at all if the admin toggles the setting off and on again. Isn&#039;t the life of a developer simple and wonderful?&lt;br /&gt;
&lt;br /&gt;
=== Exercise === &lt;br /&gt;
We will let this part of the tutorial come to a close with the obligatory exercise for the reader: &lt;br /&gt;
In order to have the SimpleHTML block work &amp;quot;correctly&amp;quot;, find out how to strengthen the eager approach to strip out all tags from the existing configuration of all instances of our block, &#039;&#039;&#039;or&#039;&#039;&#039; go back and implement the lazy approach instead. &lt;br /&gt;
(Hint: Do that in the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Eye Candy ==&lt;br /&gt;
&lt;br /&gt;
Our block is just about complete functionally, so now let&#039;s take a look at some of the tricks we can use to make its behavior customized in a few more useful ways.&lt;br /&gt;
&lt;br /&gt;
First of all, there are a couple of ways we can adjust the visual aspects of our block. For starters, it might be useful to create a block that doesn&#039;t display a header (title) at all. You can see this effect in action in the Course Description block that comes with Moodle. This behavior is achieved by, you guessed it, adding one more method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function hide_header() {&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One more note here: we cannot just set an empty title inside the block&#039;s [[Blocks/Appendix_A#init.28.29| init()]] method; it&#039;s necessary for each block to have a unique, non-empty title after [[Blocks/Appendix_A#init.28.29| init()]] is called so that Moodle can use those titles to differentiate between all of the installed blocks.&lt;br /&gt;
&lt;br /&gt;
Next, we can affect some properties of the actual HTML that will be used to print our block. Each block is fully contained within a &amp;amp;lt;div&amp;amp;gt; or &amp;amp;lt;table&amp;amp;gt; elements, inside which all the HTML for that block is printed. We can instruct Moodle to add HTML attributes with specific values to that container. This is generally done to give us freedom to customize the end result using CSS (this is in fact done by default as we&#039;ll see below).&lt;br /&gt;
&lt;br /&gt;
The default behavior of this feature in our case will modify our block&#039;s &amp;quot;class&amp;quot; HTML attribute by appending the value &amp;quot;block_simplehtml&amp;quot; (the prefix &amp;quot;block_&amp;quot; followed by the name of our block, lowercased). We can then use that class to make CSS selectors in our theme to alter this block&#039;s visual style (for example, &amp;quot;.block_simplehtml { border: 1px black solid}&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To change the default behavior, we will need to define a method which returns an associative array of attribute names and values. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function html_attributes() {&lt;br /&gt;
    $attributes = parent::html_attributes(); // Get default values&lt;br /&gt;
    $attributes[&#039;class&#039;] .= &#039; block_&#039;. $this-&amp;gt;name(); // Append our class to class attribute&lt;br /&gt;
    return $attributes;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This results in the block having all its normal HTML attributes, as inherited from the base block class, plus our additional class name. We can now use this class name to change the style of the block, add JavaScript events to it via YUI, and so on. And for one final elegant touch,  we have not set the class to the hard-coded value &amp;quot;block_simplehtml&amp;quot;, but instead used the [[Blocks/Appendix_A#name.28.29| name()]] method to make it dynamically match our block&#039;s name.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Authorized Personnel Only ==&lt;br /&gt;
&lt;br /&gt;
Some blocks are useful in some circumstances, but not in others. An example of this would be the &amp;quot;Social Activities&amp;quot; block, which is useful in courses with the &amp;quot;social&amp;quot; course format, but not courses with the &amp;quot;weeks&amp;quot; format. What we need to be able to do is limit our block&#039;s availability, so that it can only be selected on pages where its content or abilities are appropriate.&lt;br /&gt;
&lt;br /&gt;
Moodle allows us to declare which page formats a block is available on, and enforces these restrictions as set by the block&#039;s developer at all times. The information is given to Moodle as a standard associative array, with each key corresponding to a page format and defining a boolean value (true/false) that declares whether the block should be allowed to appear in that page format.&lt;br /&gt;
&lt;br /&gt;
Notice the deliberate use of the term &#039;&#039;page&#039;&#039; instead of &#039;&#039;course&#039;&#039; in the above paragraph. This is because in Moodle 1.5 and onwards, blocks can be displayed in any page that supports them. The best example of such pages are the course pages, but we are not restricted to them. For instance, the quiz view page (the first one we see when we click on the name of the quiz) also supports blocks.&lt;br /&gt;
&lt;br /&gt;
The format names we can use for the pages derive from the name of the script which is actually used to display that page. For example, when we are looking at a course, the script is &amp;lt;span class=&amp;quot;filename&amp;quot;&amp;gt;/course/view.php&amp;lt;/span&amp;gt; (this is evident from the browser&#039;s address line). Thus, the format name of that page is &#039;&#039;&#039;course-view&#039;&#039;&#039;. It follows easily that the format name for a quiz view page is &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039;. This rule of thumb does have a few exceptions, however:&lt;br /&gt;
&lt;br /&gt;
# The format name for the front page of Moodle is &#039;&#039;&#039;site-index&#039;&#039;&#039;.&lt;br /&gt;
# The format name for courses is actually not just &#039;&#039;&#039;course-view&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;; it is &amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;course-view-weeks&#039;&#039;&#039;, &#039;&#039;&#039;course-view-topics&#039;&#039;&#039;, etc.&lt;br /&gt;
# Even though there is no such page, the format name &#039;&#039;&#039;all&#039;&#039;&#039; can be used as a catch-all option.&lt;br /&gt;
&lt;br /&gt;
We can include as many format names as we want in our definition of the applicable formats. Each format can be allowed or disallowed, and there are also three more rules that help resolve the question &amp;quot;is this block allowed into this page or not?&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
# Prefixes of a format name will match that format name; for example, &#039;&#039;&#039;mod&#039;&#039;&#039; will match all the activity modules. &#039;&#039;&#039;course-view&#039;&#039;&#039; will match any course, regardless of the course format. And finally, &#039;&#039;&#039;site&#039;&#039;&#039; will also match the front page (remember that its full format name is &#039;&#039;&#039;site-index&#039;&#039;&#039;).&lt;br /&gt;
# The more specialized a format name that matches our page is, the higher precedence it has when deciding if the block will be allowed. For example, &#039;&#039;&#039;mod&#039;&#039;&#039;, &#039;&#039;&#039;mod-quiz&#039;&#039;&#039; and &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039; all match the quiz view page. But if all three are present, &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039; will take precedence over the other two because it is a better match.&lt;br /&gt;
# The character &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;*&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039; can be used in place of any word. For example, &#039;&#039;&#039;mod&#039;&#039;&#039; and &#039;&#039;&#039;mod-*&#039;&#039;&#039; are equivalent. At the time of this document&#039;s writing, there is no actual reason to utilize this &amp;quot;wildcard matching&amp;quot; feature, but it exists for future usage.&lt;br /&gt;
# The order that the format names appear does not make any difference.&lt;br /&gt;
All of the above are enough to make the situation sound complex, so let&#039;s look at some specific examples. First of all, to have our block appear &#039;&#039;&#039;only&#039;&#039;&#039; in the site front page, we would use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
public function applicable_formats() {&lt;br /&gt;
  return array(&#039;site-index&#039; =&amp;gt; true);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Since &#039;&#039;&#039;all&#039;&#039;&#039; is missing, the block is disallowed from appearing in &#039;&#039;any&#039;&#039; course format; but then &#039;&#039;&#039;site&#039;&#039;&#039; is set to TRUE, so it&#039;s explicitly allowed to appear in the site front page (remember that &#039;&#039;&#039;site&#039;&#039;&#039; matches &#039;&#039;&#039;site-index&#039;&#039;&#039; because it&#039;s a prefix).&lt;br /&gt;
&lt;br /&gt;
For another example, if we wanted to allow the block to appear in all course formats &#039;&#039;except&#039;&#039; social, and also to &#039;&#039;not&#039;&#039; be allowed anywhere but in courses, we would use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
public function applicable_formats() {&lt;br /&gt;
  return array(&lt;br /&gt;
           &#039;course-view&#039; =&amp;gt; true, &lt;br /&gt;
    &#039;course-view-social&#039; =&amp;gt; false);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This time, we first allow the block to appear in all courses and then we explicitly disallow the social format.&lt;br /&gt;
For our final, most complicated example, suppose that a block can be displayed in the site front page, in courses (but not social courses) and also when we are viewing any activity module, &#039;&#039;except&#039;&#039; quiz. This would be:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function applicable_formats() {&lt;br /&gt;
  return array(&lt;br /&gt;
           &#039;site-index&#039; =&amp;gt; true,&lt;br /&gt;
          &#039;course-view&#039; =&amp;gt; true, &lt;br /&gt;
   &#039;course-view-social&#039; =&amp;gt; false,&lt;br /&gt;
                  &#039;mod&#039; =&amp;gt; true, &lt;br /&gt;
             &#039;mod-quiz&#039; =&amp;gt; false&lt;br /&gt;
  );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is not difficult to realize that the above accomplishes the objective if we remember that there is a &amp;quot;best match&amp;quot; policy to determine the end result.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Background Processing ==&lt;br /&gt;
&lt;br /&gt;
If you want to do some background processing in your block - use the [[Task API]] to create a background task that can be scheduled to run at regular intervals and can be displayed and configured by an administrator (this is the same regardless of the plugin type).&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Additional Content Types == &lt;br /&gt;
&lt;br /&gt;
=== Lists ===&lt;br /&gt;
&lt;br /&gt;
In this final part of the guide we will briefly discuss several additional capabilities of Moodle&#039;s block system, namely the ability to create blocks that display different kinds of content to the user. The first of these creates a list of options and displays them to the user.  This list is displayed with one item per line, and an optional image (icon) next to the item. An example of such a &#039;&#039;list block&#039;&#039; is the standard Moodle &amp;quot;admin&amp;quot; block, which illustrates all the points discussed in this section.&lt;br /&gt;
&lt;br /&gt;
As we have seen so far, blocks use two properties of [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]]: &amp;quot;text&amp;quot; and &amp;quot;footer&amp;quot;. The text is displayed as-is as the block content, and the footer is displayed below the content in a smaller font size. List blocks use $this-&amp;gt;content-&amp;gt;footer in the exact same way, but they ignore $this-&amp;gt;content-&amp;gt;text.&lt;br /&gt;
&lt;br /&gt;
Instead, Moodle expects such blocks to set two other properties when the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method is called: $this-&amp;gt;content-&amp;gt;items and $this-&amp;gt;content-&amp;gt;icons. $this-&amp;gt;content-&amp;gt;items should be a numerically indexed array containing elements that represent the HTML for each item in the list that is going to be displayed. Usually these items will be HTML anchor tags which provide links to some page. $this-&amp;gt;content-&amp;gt;icons should also be a numerically indexed array, with exactly as many items as $this-&amp;gt;content-&amp;gt;items has. Each of these items should be a fully qualified HTML &amp;lt;img&amp;gt; tag, with &amp;quot;src&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;width&amp;quot; and &amp;quot;alt&amp;quot; attributes. Obviously, it makes sense to keep the images small and of a uniform size. We would recommend standard 16x16 images for this purpose.&lt;br /&gt;
&lt;br /&gt;
In order to tell Moodle that we want to have a list block instead of the standard text block, we need to make a small change to our block class declaration. Instead of extending class &#039;&#039;&#039;block_base&#039;&#039;&#039;, our block will extend class &#039;&#039;&#039;block_list&#039;&#039;&#039;. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
class block_my_menu extends block_list {&lt;br /&gt;
     // The init() method does not need to change at all&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition to making this change, we must of course also modify the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method to construct the [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]] variable as discussed above:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
public function get_content() {&lt;br /&gt;
  if ($this-&amp;gt;content !== null) {&lt;br /&gt;
    return $this-&amp;gt;content;&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  $this-&amp;gt;content         = new stdClass;&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;items  = array();&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;icons  = array();&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;footer = &#039;Footer here...&#039;;&lt;br /&gt;
 &lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;items[] = html_writer::tag(&#039;a&#039;, &#039;Menu Option 1&#039;, array(&#039;href&#039; =&amp;gt; &#039;some_file.php&#039;));&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;icons[] = html_writer::empty_tag(&#039;img&#039;, array(&#039;src&#039; =&amp;gt; &#039;images/icons/1.gif&#039;, &#039;class&#039; =&amp;gt; &#039;icon&#039;));&lt;br /&gt;
&lt;br /&gt;
  // Add more list items here&lt;br /&gt;
 &lt;br /&gt;
  return $this-&amp;gt;content;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To summarise, if we want to create a list block instead of a text block, we just need to change the block class declaration and the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method. Adding the mandatory [[Blocks/Appendix_A#init.28.29| init()]] method as discussed earlier will then give us our first list block in no time!&lt;br /&gt;
&lt;br /&gt;
=== Trees ===&lt;br /&gt;
&lt;br /&gt;
As of 23rd December 2011, this functionality remains inoperable in all Moodle 2.x versions. It appears that classes are missing from the code base. This has been added to the tracker at the URL below. Please upvote this issue if you require this functionality.&lt;br /&gt;
&lt;br /&gt;
[http://tracker.moodle.org/browse/MDL-28289 Visit this issue on the tracker @ MDL28289]&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Database support ==&lt;br /&gt;
In case we need to have a database table that holds some specific information used within our block, we will need to create the file &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;install.xml&#039;&#039;&#039;&#039;&#039; with the table schema contained within it.&lt;br /&gt;
&lt;br /&gt;
To create the install.xml file, use the [[XMLDB editor]]. See [[Database_FAQ#XMLDB|Database FAQ &amp;gt; XMLDB]] for further details.&lt;br /&gt;
&lt;br /&gt;
Up-to-date documentation on upgrading our block, as well as providing new capabilities and events to the system, can be found under [https://docs.moodle.org/dev/Installing_and_upgrading_plugin_database_tables#install.php Installing and Upgrading Plugin Database Tables]&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Blocks Advanced]] A continuation of this tutorial.&lt;br /&gt;
* [http://dev.moodle.org/mod/resource/view.php?id=48 Unit 7 of the Introduction to Moodle Programming course] is a follow up to this course. (But you should follow the forum discussions of that course closely as there are still some bugs and inconsistencies.)&lt;br /&gt;
* Daniel Neis Araujo&#039;s [https://github.com/danielneis/moodle-block_newblock NEWBLOCK template].&lt;br /&gt;
&lt;br /&gt;
== Appendices ==&lt;br /&gt;
&lt;br /&gt;
The appendices have been moved to separate pages:&lt;br /&gt;
&lt;br /&gt;
* Appendix A: [[Blocks/Appendix A|&#039;&#039;block_base&#039;&#039; Reference]] &lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Blocks]]&lt;br /&gt;
[[Category:Tutorial]]&lt;br /&gt;
&lt;br /&gt;
[[es:Desarrollo de bloques]]&lt;br /&gt;
[[ja:開発:ブロック]]&lt;br /&gt;
[[:en:Blocks|Blocks]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Meeth</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Creating_a_theme_based_on_boost&amp;diff=57604</id>
		<title>Creating a theme based on boost</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Creating_a_theme_based_on_boost&amp;diff=57604"/>
		<updated>2020-06-14T15:52:05Z</updated>

		<summary type="html">&lt;p&gt;Meeth: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 3.2}}&lt;br /&gt;
{{Template:Themes}}&lt;br /&gt;
&lt;br /&gt;
This is a tutorial for how to create a new theme in any version of Moodle from 3.2 and later.&lt;br /&gt;
&lt;br /&gt;
Moodle 3.2 introduced a new core theme named &amp;quot;Boost&amp;quot; which is a great starting point for themers wanting to build a modern Moodle theme utilising all the latest features available to themes in Moodle.  If you aren&#039;t sure where to start, then START HERE!  :-)&lt;br /&gt;
&lt;br /&gt;
== Getting started ==&lt;br /&gt;
What is a theme? A theme in Moodle is just another type of plugin that can be developed. Themes are responsible for setting up the structure of each page and have the ability to customise the output of any page in Moodle.&lt;br /&gt;
&lt;br /&gt;
This tutorial is based on a working theme named &amp;quot;theme_photo&amp;quot; you can download it or view the source code for it here: https://github.com/damyon/moodle-theme_photo&lt;br /&gt;
&lt;br /&gt;
=== Choosing a name ===&lt;br /&gt;
Your new theme will need a name. Try and think of something short and memorable - and make sure it is not a name that has already been used by someone else. A quick search on the moodle.org/plugins can save you a lot of work renaming things later.&lt;br /&gt;
&lt;br /&gt;
Lets call our new example theme &amp;quot;photo&amp;quot; as we will add some settings to allow &amp;quot;photos&amp;quot; in various places in Moodle.&lt;br /&gt;
&lt;br /&gt;
=== Starting files ===&lt;br /&gt;
As a plugin, themes must start with the basic structure of a plugin in Moodle. See https://docs.moodle.org/dev/Tutorial#The_skeleton_of_your_plugin for an overview of the files common to all plugins in Moodle.&lt;br /&gt;
&lt;br /&gt;
Following this guide we can start creating our theme. First we create the folder for the new theme under &amp;quot;/theme/&amp;quot; folder in the Moodle root directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
/theme/photo/&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we need to add some standard plugin files to our theme. First is version.php&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/theme/photo/version.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the version of the plugin.                                                                                               &lt;br /&gt;
$plugin-&amp;gt;version = &#039;2016102100&#039;;                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the version of Moodle this plugin requires.                                                                              &lt;br /&gt;
$plugin-&amp;gt;requires = &#039;2016070700&#039;;                                                                                                   &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is the component name of the plugin - it always starts with &#039;theme_&#039;                                                        &lt;br /&gt;
// for themes and should be the same as the name of the folder.                                                                     &lt;br /&gt;
$plugin-&amp;gt;component = &#039;theme_photo&#039;;                                                                                                 &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a list of plugins, this plugin depends on (and their versions).                                                          &lt;br /&gt;
$plugin-&amp;gt;dependencies = [                                                                                                           &lt;br /&gt;
    &#039;theme_boost&#039; =&amp;gt; &#039;2016102100&#039;                                                                                                   &lt;br /&gt;
];                                                                              &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need a language file so that all our strings can be translated into different languages. The name of this file is the component name of our plugin and it sits in the lang/en/ folder for our plugin. We can include translations of our plugin, but we can also provide translations via the https://lang.moodle.org/ website once our plugin has been published to the plugins database at http://www.moodle.org/plugins/.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/theme/photo/lang/en/theme_photo.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// A description shown in the admin theme selector.                                                                                 &lt;br /&gt;
$string[&#039;choosereadme&#039;] = &#039;Theme photo is a child theme of Boost. It adds the ability to upload background photos.&#039;;                &lt;br /&gt;
// The name of our plugin.                                                                                                          &lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Photo&#039;;                                                                                                    &lt;br /&gt;
// We need to include a lang string for each block region.                                                                          &lt;br /&gt;
$string[&#039;region-side-pre&#039;] = &#039;Right&#039;;                                         &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Theme specific files ===&lt;br /&gt;
Theme plugins have a few more standard files they need to define. &lt;br /&gt;
&lt;br /&gt;
Themes require a favicon file to show in the address bar. See [[http://docs.moodle.org/en/Favicon Favicon]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;pix/favicon.ico&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(Image file not shown).&lt;br /&gt;
&lt;br /&gt;
Themes also require an example screenshot to be displayed in the theme selector.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;pix/screenshot.jpg&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(Image file not shown).&lt;br /&gt;
&lt;br /&gt;
Themes require a lib.php file. This file contains callbacks used by various API&#039;s in Moodle. Initially this file can be empty, but as we add features to our theme we will need to add some functions here.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
// We will add callbacks here as we add features to our theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Theme config goes in a config.php file. This is one of the most important files in our theme. Once we add this file we will be ready to test our theme for the first time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
// $THEME is defined before this page is included and we can define settings by adding properties to this global object.            &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// The first setting we need is the name of the theme. This should be the last part of the component name, and the same             &lt;br /&gt;
// as the directory name for our theme.                                                                                             &lt;br /&gt;
$THEME-&amp;gt;name = &#039;photo&#039;;                                                                                                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This setting list the style sheets we want to include in our theme. Because we want to use SCSS instead of CSS - we won&#039;t        &lt;br /&gt;
// list any style sheets. If we did we would list the name of a file in the /style/ folder for our theme without any css file      &lt;br /&gt;
// extensions.                                                                                                                      &lt;br /&gt;
$THEME-&amp;gt;sheets = [];                                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a setting that can be used to provide some styling to the content in the TinyMCE text editor. This is no longer the      &lt;br /&gt;
// default text editor and &amp;quot;Atto&amp;quot; does not need this setting so we won&#039;t provide anything. If we did it would work the same         &lt;br /&gt;
// as the previous setting - listing a file in the /styles/ folder.                                                                 &lt;br /&gt;
$THEME-&amp;gt;editor_sheets = [];                                                                                                         &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a critical setting. We want to inherit from theme_boost because it provides a great starting point for SCSS bootstrap4   &lt;br /&gt;
// themes. We could add more than one parent here to inherit from multiple parents, and if we did they would be processed in        &lt;br /&gt;
// order of importance (later themes overriding earlier ones). Things we will inherit from the parent theme include                 &lt;br /&gt;
// styles and mustache templates and some (not all) settings.                                                                       &lt;br /&gt;
$THEME-&amp;gt;parents = [&#039;boost&#039;];                                                                                                        &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// A dock is a way to take blocks out of the page and put them in a persistent floating area on the side of the page. Boost         &lt;br /&gt;
// does not support a dock so we won&#039;t either - but look at bootstrapbase for an example of a theme with a dock.                    &lt;br /&gt;
$THEME-&amp;gt;enable_dock = false;                                                                                                        &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is an old setting used to load specific CSS for some YUI JS. We don&#039;t need it in Boost based themes because Boost           &lt;br /&gt;
// provides default styling for the YUI modules that we use. It is not recommended to use this setting anymore.                     &lt;br /&gt;
$THEME-&amp;gt;yuicssmodules = array();                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// Most themes will use this rendererfactory as this is the one that allows the theme to override any other renderer.               &lt;br /&gt;
$THEME-&amp;gt;rendererfactory = &#039;theme_overridden_renderer_factory&#039;;                                                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is a list of blocks that are required to exist on all pages for this theme to function correctly. For example               &lt;br /&gt;
// bootstrap base requires the settings and navigation blocks because otherwise there would be no way to navigate to all the        &lt;br /&gt;
// pages in Moodle. Boost does not require these blocks because it provides other ways to navigate built into the theme.            &lt;br /&gt;
$THEME-&amp;gt;requiredblocks = &#039;&#039;;   &lt;br /&gt;
&lt;br /&gt;
// This is a feature that tells the blocks library not to use the &amp;quot;Add a block&amp;quot; block. We don&#039;t want this in boost based themes because&lt;br /&gt;
// it forces a block region into the page when editing is enabled and it takes up too much room.&lt;br /&gt;
$THEME-&amp;gt;addblockposition = BLOCK_ADDBLOCK_POSITION_FLATNAV;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ready set go! ===&lt;br /&gt;
If you have been following along - now we are at the point where we can actually install and test our new theme. Try it now by visiting the admin notifications page to install the new plugin, and then choosing the new theme from the theme selector.&lt;br /&gt;
&lt;br /&gt;
[[https://docs.moodle.org/en/Standard_themes#Theme_selector Theme selector]]&lt;br /&gt;
&lt;br /&gt;
When you choose the new theme - you will find that it looks exactly the same as Boost. At this point with our minimal configuration - we are inheriting almost everything from our parent theme including styles and templates. You will notice though that we don&#039;t inherit the settings from our parent theme. If you choose a different preset in Boost - it is not applied in this child theme.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&lt;br /&gt;
Note: make sure your config.php file contains $THEME-&amp;gt;hidefromselector = false; (or at least set to false) or else, your theme wont show up in theme selector.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What if I want the settings too? ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&lt;br /&gt;
This section is included for completeness - but it is not recommended for themes to utilise settings from their parents. To find out how to duplicate the settings from the parent theme so they operate independently skip to [[#Duplicate the settings from Boost]].&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If I want the settings from Boost to apply to my child theme as well I need to know a bit about how each of the settings in Boost is applied to make them work in my child theme.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Setting 1 - preset.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;preset&amp;quot; file is the file that is used as the main file for scss compilation. In Boost this is controlled by the theme config value:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {&lt;br /&gt;
    return theme_boost_get_main_scss_content($theme);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_boost&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this function is doing is checking for a theme setting &amp;quot;preset&amp;quot; and either fetching the file from Moodles internal file storage, or from the /preset/ folder. The function then returns the contents of this file.&lt;br /&gt;
&lt;br /&gt;
It does not automatically work for our child theme because we have no setting named &amp;quot;preset&amp;quot; in our child theme and this code is not searching the theme parents for the setting. If we wanted it to apply we could do this in our child theme:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This setting defines the main scss file for our theme to be compiled. We could set it to a static file in the scss folder or to a function which returns the SCSS based on theme settings.&lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {&lt;br /&gt;
&lt;br /&gt;
    // We need to load the config for our parent theme because that is where the preset setting is defined.&lt;br /&gt;
    $parentconfig = theme_config::load(&#039;boost&#039;);&lt;br /&gt;
    // Call a function from our parent themes lib.php file to fetch the content of the themes main SCSS file based on it&#039;s own config, not ours.&lt;br /&gt;
    return theme_boost_get_main_scss_content($parentconfig);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings 2+3 brandcolor + scsspre&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The way these settings work is they generate a chunk of SCSS to be prepended to the main scss file. In boost they work like this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;prescsscallback = &#039;theme_boost_get_pre_scss&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_pre_scss($theme) {                                                                                         &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $configurable = [                                                                                                               &lt;br /&gt;
        // Config key =&amp;gt; [variableName, ...].                                                                                       &lt;br /&gt;
        &#039;brandcolor&#039; =&amp;gt; [&#039;brand-primary&#039;],                                                                                          &lt;br /&gt;
    ];                                                                                                                              &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Prepend variables first.                                                                                                     &lt;br /&gt;
    foreach ($configurable as $configkey =&amp;gt; $targets) {                                                                             &lt;br /&gt;
        $value = isset($theme-&amp;gt;settings-&amp;gt;{$configkey}) ? $theme-&amp;gt;settings-&amp;gt;{$configkey} : null;                                     &lt;br /&gt;
        if (empty($value)) {                                                                                                        &lt;br /&gt;
            continue;                                                                                                               &lt;br /&gt;
        }                                                                                                                           &lt;br /&gt;
        array_map(function($target) use (&amp;amp;$scss, $value) {                                                                          &lt;br /&gt;
            $scss .= &#039;$&#039; . $target . &#039;: &#039; . $value . &amp;quot;;\n&amp;quot;;                                                                         &lt;br /&gt;
        }, (array) $targets);                                                                                                       &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Prepend pre-scss.                                                                                                            &lt;br /&gt;
    if (!empty($theme-&amp;gt;settings-&amp;gt;scsspre)) {                                                                                        &lt;br /&gt;
        $scss .= $theme-&amp;gt;settings-&amp;gt;scsspre;                                                                                         &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}  &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this code is doing is: &lt;br /&gt;
* looping over a list of theme settings that map to a SCSS variable and building some SCSS to initialise that variable from the setting. In Boost there is only one * brandprimary - but if we wanted to expose more bootstrap variables as theme settings we could use this function as a template in our child theme and add more settings to the $configurable array.&lt;br /&gt;
* Adding all of the raw SCSS from the scsspre theme setting&lt;br /&gt;
* Returning the whole thing as a string to be added before the main scss file.&lt;br /&gt;
&lt;br /&gt;
If we want this code to work in our child theme, using the settings from Boost we could do this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is a function that returns some SCSS as a string to prepend to the main SCSS file.                                          &lt;br /&gt;
$THEME-&amp;gt;prescsscallback = &#039;theme_photo_get_pre_scss&#039;;               &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Function to return the SCSS to prepend to our main SCSS for this theme.&lt;br /&gt;
// Note the function name starts with the component name because this is a global function and we don&#039;t want namespace clashes.&lt;br /&gt;
function theme_photo_get_pre_scss($theme) {&lt;br /&gt;
    // Load the settings from the parent.                                                                                           &lt;br /&gt;
    $theme = theme_config::load(&#039;boost&#039;);                                                                                           &lt;br /&gt;
    // Call the parent themes get_pre_scss function.                                                                                &lt;br /&gt;
    return theme_boost_get_pre_scss($theme);                         &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Setting 4 scss (post)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The final setting from Boost is a raw text field which adds SCSS to the end of the main SCSS file. This is a useful place to add style rules as they will override previously defined styles with the same specificity. It is applied in Boost by the following lines:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;theme_boost/config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$THEME-&amp;gt;extrascsscallback = &#039;theme_boost_get_extra_scss&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;theme_boost/lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_boost_get_extra_scss($theme) {                                                                                       &lt;br /&gt;
    return !empty($theme-&amp;gt;settings-&amp;gt;scss) ? $theme-&amp;gt;settings-&amp;gt;scss : &#039;&#039;;                                                            &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is just returning the value of the setting as a string.&lt;br /&gt;
&lt;br /&gt;
To make this setting apply in our child theme too - we use similar code to the previous sections.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is a function that returns some SCSS as a string to append to the main SCSS file.                                          &lt;br /&gt;
$THEME-&amp;gt;extrascsscallback = &#039;theme_photo_get_extra_scss&#039;;               &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Function to return the SCSS to append to our main SCSS for this theme.&lt;br /&gt;
// Note the function name starts with the component name because this is a global function and we don&#039;t want namespace clashes.&lt;br /&gt;
function theme_photo_get_extra_scss($theme) {&lt;br /&gt;
    // Load the settings from the parent.                                                                                           &lt;br /&gt;
    $theme = theme_config::load(&#039;boost&#039;);                                                                                           &lt;br /&gt;
    // Call the parent themes get_extra_scss function.                                                                                &lt;br /&gt;
    return theme_boost_get_extra_scss($theme);                         &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Duplicate the settings from Boost  ===&lt;br /&gt;
&lt;br /&gt;
This is the recommended way to extend boost as your child theme will not be affected by changes to the Boost settings, and both themes can be in use with different settings applied.&lt;br /&gt;
&lt;br /&gt;
All that needs to happen is to create theme settings in the child theme that match each of the settings in the parent theme. You will need to add matching language strings for each of these settings in the language file.&lt;br /&gt;
&lt;br /&gt;
This example shows how to do it - We are re-using the nice looking theme_boost_admin_settingspage_tabs class from boost and creating duplicate versions of each of the settings.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();                                                                                                &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
// This is used for performance, we don&#039;t need to know about these settings on every page in Moodle, only when                      &lt;br /&gt;
// we are looking at the admin settings pages.                                                                                      &lt;br /&gt;
if ($ADMIN-&amp;gt;fulltree) {                                                                                                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Boost provides a nice setting page which splits settings onto separate tabs. We want to use it here.                         &lt;br /&gt;
    $settings = new theme_boost_admin_settingspage_tabs(&#039;themesettingphoto&#039;, get_string(&#039;configtitle&#039;, &#039;theme_photo&#039;));             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Each page is a tab - the first is the &amp;quot;General&amp;quot; tab.                                                                         &lt;br /&gt;
    $page = new admin_settingpage(&#039;theme_photo_general&#039;, get_string(&#039;generalsettings&#039;, &#039;theme_photo&#039;));                             &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Replicate the preset setting from boost.                                                                                     &lt;br /&gt;
    $name = &#039;theme_photo/preset&#039;;                                                                                                   &lt;br /&gt;
    $title = get_string(&#039;preset&#039;, &#039;theme_photo&#039;);                                                                                   &lt;br /&gt;
    $description = get_string(&#039;preset_desc&#039;, &#039;theme_photo&#039;);                                                                        &lt;br /&gt;
    $default = &#039;default.scss&#039;;                                                                                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // We list files in our own file area to add to the drop down. We will provide our own function to                              &lt;br /&gt;
    // load all the presets from the correct paths.                                                                                 &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
    $files = $fs-&amp;gt;get_area_files($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;itemid, filepath, filename&#039;, false);                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $choices = [];                                                                                                                  &lt;br /&gt;
    foreach ($files as $file) {                                                                                                     &lt;br /&gt;
        $choices[$file-&amp;gt;get_filename()] = $file-&amp;gt;get_filename();                                                                    &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
    // These are the built in presets from Boost.                                                                                   &lt;br /&gt;
    $choices[&#039;default.scss&#039;] = &#039;default.scss&#039;;                                                                                      &lt;br /&gt;
    $choices[&#039;plain.scss&#039;] = &#039;plain.scss&#039;;                                                                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $setting = new admin_setting_configselect($name, $title, $description, $default, $choices);                                     &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Preset files setting.                                                                                                        &lt;br /&gt;
    $name = &#039;theme_photo/presetfiles&#039;;                                                                                              &lt;br /&gt;
    $title = get_string(&#039;presetfiles&#039;,&#039;theme_photo&#039;);                                                                               &lt;br /&gt;
    $description = get_string(&#039;presetfiles_desc&#039;, &#039;theme_photo&#039;);                                                                   &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;preset&#039;, 0,                                         &lt;br /&gt;
        array(&#039;maxfiles&#039; =&amp;gt; 20, &#039;accepted_types&#039; =&amp;gt; array(&#039;.scss&#039;)));                                                               &lt;br /&gt;
    $page-&amp;gt;add($setting);     &lt;br /&gt;
&lt;br /&gt;
    // Variable $brand-color.                                                                                                       &lt;br /&gt;
    // We use an empty default value because the default colour should come from the preset.                                        &lt;br /&gt;
    $name = &#039;theme_photo/brandcolor&#039;;                                                                                               &lt;br /&gt;
    $title = get_string(&#039;brandcolor&#039;, &#039;theme_photo&#039;);                                                                               &lt;br /&gt;
    $description = get_string(&#039;brandcolor_desc&#039;, &#039;theme_photo&#039;);                                                                    &lt;br /&gt;
    $setting = new admin_setting_configcolourpicker($name, $title, $description, &#039;&#039;);                                               &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Must add the page after definiting all the settings!                                                                         &lt;br /&gt;
    $settings-&amp;gt;add($page);                                                                                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Advanced settings.                                                                                                           &lt;br /&gt;
    $page = new admin_settingpage(&#039;theme_photo_advanced&#039;, get_string(&#039;advancedsettings&#039;, &#039;theme_photo&#039;));                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Raw SCSS to include before the content.                                                                                      &lt;br /&gt;
    $setting = new admin_setting_configtextarea(&#039;theme_photo/scsspre&#039;,                                                              &lt;br /&gt;
        get_string(&#039;rawscsspre&#039;, &#039;theme_photo&#039;), get_string(&#039;rawscsspre_desc&#039;, &#039;theme_photo&#039;), &#039;&#039;, PARAM_RAW);                      &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Raw SCSS to include after the content.                                                                                       &lt;br /&gt;
    $setting = new admin_setting_configtextarea(&#039;theme_photo/scss&#039;, get_string(&#039;rawscss&#039;, &#039;theme_photo&#039;),                           &lt;br /&gt;
        get_string(&#039;rawscss_desc&#039;, &#039;theme_photo&#039;), &#039;&#039;, PARAM_RAW);                                                                  &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    $page-&amp;gt;add($setting);                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $settings-&amp;gt;add($page);                                                                                                          &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lang/en/theme_photo.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// Every file should have GPL and copyright in the header - we skip it in tutorials but you should not skip it for real.&lt;br /&gt;
&lt;br /&gt;
// This line protects the file from being accessed by a URL directly.                                                               &lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
// The name of the second tab in the theme settings.                                                                                &lt;br /&gt;
$string[&#039;advancedsettings&#039;] = &#039;Advanced settings&#039;;                                                                                  &lt;br /&gt;
// The brand colour setting.                                                                                                        &lt;br /&gt;
$string[&#039;brandcolor&#039;] = &#039;Brand colour&#039;;                                                                                             &lt;br /&gt;
// The brand colour setting description.                                                                                            &lt;br /&gt;
$string[&#039;brandcolor_desc&#039;] = &#039;The accent colour.&#039;;     &lt;br /&gt;
// A description shown in the admin theme selector.                                                                                 &lt;br /&gt;
$string[&#039;choosereadme&#039;] = &#039;Theme photo is a child theme of Boost. It adds the ability to upload background photos.&#039;;                &lt;br /&gt;
// Name of the settings pages.                                                                                                      &lt;br /&gt;
$string[&#039;configtitle&#039;] = &#039;Photo settings&#039;;                                                                                          &lt;br /&gt;
// Name of the first settings tab.                                                                                                  &lt;br /&gt;
$string[&#039;generalsettings&#039;] = &#039;General settings&#039;;                                                                                    &lt;br /&gt;
// The name of our plugin.                                                                                                          &lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Photo&#039;;                                                                                                    &lt;br /&gt;
// Preset files setting.                                                                                                            &lt;br /&gt;
$string[&#039;presetfiles&#039;] = &#039;Additional theme preset files&#039;;                                                                           &lt;br /&gt;
// Preset files help text.                                                                                                          &lt;br /&gt;
$string[&#039;presetfiles_desc&#039;] = &#039;Preset files can be used to dramatically alter the appearance of the theme. See &amp;lt;a href=https://docs.moodle.org/dev/Boost_Presets&amp;gt;Boost presets&amp;lt;/a&amp;gt; for information on creating and sharing your own preset files, and see the &amp;lt;a href=http://moodle.net/boost&amp;gt;Presets repository&amp;lt;/a&amp;gt; for presets that others have shared.&#039;;&lt;br /&gt;
// Preset setting.                                                                                                                  &lt;br /&gt;
$string[&#039;preset&#039;] = &#039;Theme preset&#039;;                                                                                                 &lt;br /&gt;
// Preset help text.                                                                                                                &lt;br /&gt;
$string[&#039;preset_desc&#039;] = &#039;Pick a preset to broadly change the look of the theme.&#039;;                                                  &lt;br /&gt;
// Raw SCSS setting.                                                                                                                &lt;br /&gt;
$string[&#039;rawscss&#039;] = &#039;Raw SCSS&#039;;                                                                                                    &lt;br /&gt;
// Raw SCSS setting help text.                                                                                                      &lt;br /&gt;
$string[&#039;rawscss_desc&#039;] = &#039;Use this field to provide SCSS or CSS code which will be injected at the end of the style sheet.&#039;;       &lt;br /&gt;
// Raw initial SCSS setting.                                                                                                        &lt;br /&gt;
$string[&#039;rawscsspre&#039;] = &#039;Raw initial SCSS&#039;;                                                                                         &lt;br /&gt;
// Raw initial SCSS setting help text.                                                                                              &lt;br /&gt;
$string[&#039;rawscsspre_desc&#039;] = &#039;In this field you can provide initialising SCSS code, it will be injected before everything else. Most of the time you will use this setting to define variables.&#039;;&lt;br /&gt;
// We need to include a lang string for each block region.                                                                          &lt;br /&gt;
$string[&#039;region-side-pre&#039;] = &#039;Right&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We aren&#039;t quite there yet as you will notice if you try and upload a preset file and then choose it. The &amp;quot;theme_boost_get_main_scss_content&amp;quot; function from Boost is expecting the preset files to be stored in a file area for theme_boost only. We need to add this function to our own theme and tweak it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;config.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// This is the function that returns the SCSS source for the main file in our theme. We override the boost version because          &lt;br /&gt;
// we want to allow presets uploaded to our own theme file area to be selected in the preset list.                                  &lt;br /&gt;
$THEME-&amp;gt;scss = function($theme) {                                                                                                   &lt;br /&gt;
    return theme_photo_get_main_scss_content($theme);                                                                               &lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        // This preset file was fetched from the file area for theme_photo and not theme_boost (see the line above).                &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    return $scss;                                                                                                                   &lt;br /&gt;
}             &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Stop and try it out ===&lt;br /&gt;
So now what is working and what isn&#039;t. Well - everything should be working and you should have a nice new theme extending boost with it&#039;s own settings pages. When Boost gets updates for bug fixes your new theme will inherit those fixes as it inherits all the SCSS and templates from theme boost. In addition your new theme will accept preset files and supports all the same features and settings as boost, ready to add more.&lt;br /&gt;
&lt;br /&gt;
== Take it further ==&lt;br /&gt;
Now we have our very nice starting point we can start changing or adding features, customising templates and output or tweaking the SCSS.&lt;br /&gt;
&lt;br /&gt;
=== Add some new settings ===&lt;br /&gt;
&lt;br /&gt;
From this point in the tutorial we will start adding features to our theme to extend it and make it AWESOME!&lt;br /&gt;
&lt;br /&gt;
Lets start with a new setting to set a background image on the login page. As you saw earlier, our theme defines it&#039;s list of settings in a file called settings.php. See [[Admin settings]] for more information about adding admin settings to any plugin. All of the different kinds of admin settings can be found in lib/adminlib.php. In our case we will want to add a setting which allows an admin to upload an image file. This is an &amp;quot;admin_setting_configstoredfile&amp;quot; and we add it to our theme by adding  this code to the settings.php file (inside the &amp;quot;if ($ADMIN-&amp;gt;fulltree) {&amp;quot; condition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    // Login page background setting.                                                                                               &lt;br /&gt;
    // We use variables for readability.                                                                                            &lt;br /&gt;
    $name = &#039;theme_photo/loginbackgroundimage&#039;;                                                                                     &lt;br /&gt;
    $title = get_string(&#039;loginbackgroundimage&#039;, &#039;theme_photo&#039;);                                                                     &lt;br /&gt;
    $description = get_string(&#039;loginbackgroundimage_desc&#039;, &#039;theme_photo&#039;);                                                          &lt;br /&gt;
    // This creates the new setting.                                                                                                &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;loginbackgroundimage&#039;);                             &lt;br /&gt;
    // This means that theme caches will automatically be cleared when this setting is changed.                                     &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_reset_all_caches&#039;);                                                                        &lt;br /&gt;
    // We always have to add the setting to a page for it to have any effect.                                                       &lt;br /&gt;
    $page-&amp;gt;add($setting);       &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need to add new lang strings to our language file.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lang/en/theme_photo.php&amp;quot;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Background image for login page.                                                                                                 &lt;br /&gt;
$string[&#039;loginbackgroundimage&#039;] = &#039;Login page background image&#039;;                                                                    &lt;br /&gt;
// Background image for login page.                                                                                                 &lt;br /&gt;
$string[&#039;loginbackgroundimage_desc&#039;] = &#039;An image that will be stretched to fill the background of the login page.&#039;;                 &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have a new setting that lets us upload a file - but it doesn&#039;t actually do anything yet. We need to update the theme to set this image background on the login page.&lt;br /&gt;
&lt;br /&gt;
In order to change the SCSS for our theme we will add 2 additional SCSS files and include them before and after our main scss.&lt;br /&gt;
&lt;br /&gt;
We already have a function in our lib.php file which fetches the main SCSS for our theme. This is a good point to include additional SCSS files. We can add 2 lines to the end of this function to achieve this.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_get_main_scss_content($theme) {                                                                                &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $scss = &#039;&#039;;                                                                                                                     &lt;br /&gt;
    $filename = !empty($theme-&amp;gt;settings-&amp;gt;preset) ? $theme-&amp;gt;settings-&amp;gt;preset : null;                                                 &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    $context = context_system::instance();                                                                                          &lt;br /&gt;
    if ($filename == &#039;default.scss&#039;) {                                                                                              &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    } else if ($filename == &#039;plain.scss&#039;) {                                                                                         &lt;br /&gt;
        // We still load the default preset files directly from the boost theme. No sense in duplicating them.                      &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/plain.scss&#039;);                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    } else if ($filename &amp;amp;&amp;amp; ($presetfile = $fs-&amp;gt;get_file($context-&amp;gt;id, &#039;theme_photo&#039;, &#039;preset&#039;, 0, &#039;/&#039;, $filename))) {              &lt;br /&gt;
        // This preset file was fetched from the file area for theme_photo and not theme_boost (see the line above).                &lt;br /&gt;
        $scss .= $presetfile-&amp;gt;get_content();                                                                                        &lt;br /&gt;
    } else {                                                                                                                        &lt;br /&gt;
        // Safety fallback - maybe new installs etc.                                                                                &lt;br /&gt;
        $scss .= file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/boost/scss/preset/default.scss&#039;);                                        &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Pre CSS - this is loaded AFTER any prescss from the setting but before the main scss.                                        &lt;br /&gt;
    $pre = file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/photo/scss/pre.scss&#039;);                                                         &lt;br /&gt;
    // Post CSS - this is loaded AFTER the main scss but before the extra scss from the setting.                                    &lt;br /&gt;
    $post = file_get_contents($CFG-&amp;gt;dirroot . &#039;/theme/photo/scss/post.scss&#039;);                                                       &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Combine them together.                                                                                                       &lt;br /&gt;
    return $pre . &amp;quot;\n&amp;quot; . $scss . &amp;quot;\n&amp;quot; . $post;                                                                                      &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;scss/pre.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
// Pre SCSS for the theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;scss/post.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
// Post SCSS for the theme.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Why do we use pre and post SCSS? ====&lt;br /&gt;
SCSS/SASS is a powerful language for creating CSS. It supports variables, functions, loops just like php. For lots of information and an introduction to SCSS read about [https://en.wikipedia.org/wiki/Sass_(stylesheet_language) Sass on wikipedia]. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pre SCSS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In Boost we use many variables when creating style rules.&lt;br /&gt;
&lt;br /&gt;
When declaring a variable in SCSS - it is best practice to define it like this:&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
$mycoolcolour: #FF0 !default;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this means is - if this variable is not defined already - set it to the hex value &#039;#FF0&#039;;&lt;br /&gt;
&lt;br /&gt;
So by setting this variable in some PRE scss we can override the default value of this variable everywhere it is used. Boost is built with the [https://v4-alpha.getbootstrap.com/ Bootstrap 4 (Alpha 4)] CSS Framework. This is a framework which uses SCSS to provide many extremely useful layouts and components which can be reused without adding specific CSS rules to style every page. Because bootstrap consistently uses variables we can customise many of these components easily by setting the value of the variables before we include the Bootstrap SCSS files.&lt;br /&gt;
&lt;br /&gt;
Many variables are available in /theme/boost/scss/bootstrap/_variables.scss - as an example we can change the look of all buttons and input fields with this one variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
$border-radius: 8px;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Post SCSS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Post SCSS is useful for defining full CSS rules. Because they are included last, they override any previous matching selector with the same [https://en.wikipedia.org/wiki/Cascading_Style_Sheets#Specificity Specificity].&lt;br /&gt;
&lt;br /&gt;
=== Tips for customising Moodle with SCSS (or CSS) ===&lt;br /&gt;
Some handy things to know when you are new to theming is that Moodle adds some classes to every page that helps you target a specific page or set of pages with some style rules. &lt;br /&gt;
&lt;br /&gt;
If you inspect a moodle page and look at the body tag you will see a long list of classes e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code html&amp;gt;&lt;br /&gt;
&amp;lt;body id=&amp;quot;page-course-view-weeks&amp;quot; class=&amp;quot;format-weeks  path-course path-course-view safari dir-ltr lang-en yui-skin-sam yui3-skin-sam damyon-per-in-moodle-com--stable_master pagelayout-course course-11 context-497 category-1 drawer-open-left jsenabled&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can see from this example that each page gets an id. This is a simplified representation of the current page in the navigation. In this example we are looking at the course page and this course is using the weeks format. &lt;br /&gt;
&lt;br /&gt;
The classes on the body tag can also be used to target a page or set of pages.&lt;br /&gt;
* &amp;lt;code&amp;gt;format-weeks&amp;lt;/code&amp;gt; The course format&lt;br /&gt;
* &amp;lt;code&amp;gt;path-course path-course-view&amp;lt;/code&amp;gt; The parts of the bread-crumb leading up to the current page (The current page is what goes in the id)&lt;br /&gt;
* &amp;lt;code&amp;gt;safari&amp;lt;/code&amp;gt; Some server side guessing of the browser type - it&#039;s not accurate so I would not rely on it&lt;br /&gt;
* &amp;lt;code&amp;gt;dir-ltr&amp;lt;/code&amp;gt; The direction of the current language for the page ( dir-rtl for RTL languages )&lt;br /&gt;
* &amp;lt;code&amp;gt;lang-en&amp;lt;/code&amp;gt; The current language of the page&lt;br /&gt;
* &amp;lt;code&amp;gt;yui*&amp;lt;/code&amp;gt; Legacy yui classes - ignore these&lt;br /&gt;
* &amp;lt;code&amp;gt;damyon-per-in-moodle-com--stable_master&amp;lt;/code&amp;gt; The current hostname for the site + the site name&lt;br /&gt;
* &amp;lt;code&amp;gt;pagelayout-course&amp;lt;/code&amp;gt; The layout type for the current page&lt;br /&gt;
* &amp;lt;code&amp;gt;course-11&amp;lt;/code&amp;gt; The id of the current course&lt;br /&gt;
* &amp;lt;code&amp;gt;context-497&amp;lt;/code&amp;gt; The current context id&lt;br /&gt;
* &amp;lt;code&amp;gt;category-1&amp;lt;/code&amp;gt; The category for the current course&lt;br /&gt;
* &amp;lt;code&amp;gt;drawer-open-left&amp;lt;/code&amp;gt; Added / removed when the navigation drawer is opened / closed in Boost&lt;br /&gt;
* &amp;lt;code&amp;gt;jsenabled&amp;lt;/code&amp;gt; True if the browser supports javascript&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/dev/Themes_overview#.3Cbody.3E_CSS_id_and_classes Read about Body id and classes].&lt;br /&gt;
&lt;br /&gt;
In our example the page layout is the most useful here as we have a specific page layout for login pages. We can now craft a rule that applies a background image only to login pages using &amp;quot;body.pagelayout-login&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How do we refer to an image in SCSS ? ===&lt;br /&gt;
So now we can add a rule to the post.scss which will set the background image for the login page. First we need to know how to construct a url to the background images from our stylesheet. &lt;br /&gt;
&lt;br /&gt;
In stylesheets in Moodle we can use a special pix tag to refer to images from our theme. The rule to attach the background image looks like this:&lt;br /&gt;
&#039;&#039;scss/post.scss&#039;&#039;&lt;br /&gt;
&amp;lt;code scss&amp;gt;&lt;br /&gt;
body.pagelayout-login {                                                                                                             &lt;br /&gt;
    background-image: url([[pix:theme_photo|loginbackgroundimage]]);                                                                &lt;br /&gt;
    background-size: cover;                                                                                                         &lt;br /&gt;
}                          &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are 2 important parts to this tag (the bit in square brackets). The first is &amp;quot;theme_photo&amp;quot;. In this case we are passing a component name, the image serving code in theme_config::resolve_image_location() will then look for an image file in several locations. One of these is in &amp;quot;$CFG-&amp;gt;dataroot/pix_plugins/$type/$plugin/$image&amp;quot;. We can use this to make sure the image gets served correctly by copying the file saved in the setting to this location every time it is updated. (There is an alterative way we could do this by implementing pluginfile.php in our theme - which you can read about in the [[File API]] ).&lt;br /&gt;
&lt;br /&gt;
If we had just passed the value &amp;quot;theme&amp;quot; the image serving code would have looked for the image in the &amp;quot;pix&amp;quot; folder of our theme.&lt;br /&gt;
&lt;br /&gt;
So - we need this final change to copy the image file into our dataroot each time the setting is changed.&lt;br /&gt;
&lt;br /&gt;
In the settings file we will update the callback to a new function which we will define in our lib.php.&lt;br /&gt;
&#039;&#039;settings.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Login page background setting.                                                                                               &lt;br /&gt;
    // We use variables for readability.                                                                                            &lt;br /&gt;
    $name = &#039;theme_photo/loginbackgroundimage&#039;;                                                                                     &lt;br /&gt;
    $title = get_string(&#039;loginbackgroundimage&#039;, &#039;theme_photo&#039;);                                                                     &lt;br /&gt;
    $description = get_string(&#039;loginbackgroundimage_desc&#039;, &#039;theme_photo&#039;);                                                          &lt;br /&gt;
    // This creates the new setting.                                                                                                &lt;br /&gt;
    $setting = new admin_setting_configstoredfile($name, $title, $description, &#039;loginbackgroundimage&#039;);                             &lt;br /&gt;
    // This function will copy the image into the data_root location it can be served from.                                         &lt;br /&gt;
    $setting-&amp;gt;set_updatedcallback(&#039;theme_photo_update_settings_images&#039;);                                                            &lt;br /&gt;
    // We always have to add the setting to a page for it to have any effect.                                                       &lt;br /&gt;
    $page-&amp;gt;add($setting);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib.php&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function theme_photo_update_settings_images($settingname) {                                                                         &lt;br /&gt;
    global $CFG;                                                                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // The setting name that was updated comes as a string like &#039;s_theme_photo_loginbackgroundimage&#039;.                               &lt;br /&gt;
    // We split it on &#039;_&#039; characters.                                                                                               &lt;br /&gt;
    $parts = explode(&#039;_&#039;, $settingname);                                                                                            &lt;br /&gt;
    // And get the last one to get the setting name..                                                                               &lt;br /&gt;
    $settingname = end($parts);                                                                                                     &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Admin settings are stored in system context.                                                                                 &lt;br /&gt;
    $syscontext = context_system::instance();                                                                                       &lt;br /&gt;
    // This is the component name the setting is stored in.                                                                         &lt;br /&gt;
    $component = &#039;theme_photo&#039;;                                                                                                     &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // This is the value of the admin setting which is the filename of the uploaded file.                                           &lt;br /&gt;
    $filename = get_config($component, $settingname);                                                                               &lt;br /&gt;
    // We extract the file extension because we want to preserve it.                                                                &lt;br /&gt;
    $extension = substr($filename, strrpos($filename, &#039;.&#039;) + 1);                                                                    &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // This is the path in the moodle internal file system.                                                                         &lt;br /&gt;
    $fullpath = &amp;quot;/{$syscontext-&amp;gt;id}/{$component}/{$settingname}/0{$filename}&amp;quot;;                                                      &lt;br /&gt;
    // Get an instance of the moodle file storage.                                                                                  &lt;br /&gt;
    $fs = get_file_storage();                                                                                                       &lt;br /&gt;
    // This is an efficient way to get a file if we know the exact path.                                                            &lt;br /&gt;
    if ($file = $fs-&amp;gt;get_file_by_hash(sha1($fullpath))) {                                                                           &lt;br /&gt;
        // We got the stored file - copy it to dataroot.                                                                            &lt;br /&gt;
        // This location matches the searched for location in theme_config::resolve_image_location.                                 &lt;br /&gt;
        $pathname = $CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039; . $settingname . &#039;.&#039; . $extension;                                 &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // This pattern matches any previous files with maybe different file extensions.                                            &lt;br /&gt;
        $pathpattern = $CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039; . $settingname . &#039;.*&#039;;                                          &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Make sure this dir exists.                                                                                               &lt;br /&gt;
        @mkdir($CFG-&amp;gt;dataroot . &#039;/pix_plugins/theme/photo/&#039;, $CFG-&amp;gt;directorypermissions, true);                                      &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Delete any existing files for this setting.                                                                              &lt;br /&gt;
        foreach (glob($pathpattern) as $filename) {                                                                                 &lt;br /&gt;
            @unlink($filename);                                                                                                     &lt;br /&gt;
        }                                                                                                                           &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
        // Copy the current file to this location.                                                                                  &lt;br /&gt;
        $file-&amp;gt;copy_content_to($pathname);                                                                                          &lt;br /&gt;
    }                                                                                                                               &lt;br /&gt;
                                                                                                                                    &lt;br /&gt;
    // Reset theme caches.                                                                                                          &lt;br /&gt;
    theme_reset_all_caches();                                                                                                       &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I won&#039;t show it here - but it is now easy to add a new background image setting for every layout type. I can re-use this theme_photo_update_settings_images callback for each one - so all I have to do is add the setting to the settings.php file, add the SCSS rule to the scss/post.scss file and add the lang strings to the language file.&lt;br /&gt;
&lt;br /&gt;
Thats it for this tutorial, but there are [[:Category:Themes| more Themes docs]] to browse.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Themes]]&lt;/div&gt;</summary>
		<author><name>Meeth</name></author>
	</entry>
</feed>