Merge branch 'MDL-56155-master' of git://github.com/lameze/moodle
authorEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 31 Oct 2016 16:10:58 +0000 (17:10 +0100)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 31 Oct 2016 16:11:21 +0000 (17:11 +0100)
106 files changed:
.eslintignore
.stylelintignore
admin/templates/setting_configpasswordunmask.mustache
admin/tool/lpimportcsv/lang/en/tool_lpimportcsv.php
admin/tool/mobile/lang/en/tool_mobile.php
admin/tool/usertours/classes/local/filter/role.php
admin/tool/usertours/lang/en/tool_usertours.php
admin/tool/usertours/tests/role_filter_test.php
admin/user/user_bulk_message.php
auth/ldap/lang/en/auth_ldap.php
cache/classes/dummystore.php
cache/classes/factory.php
cache/classes/helper.php
cache/classes/store.php
cache/locallib.php
cache/stores/apcu/lang/en/cachestore_apcu.php
cache/stores/apcu/lib.php
cache/stores/apcu/tests/apcu_test.php
cache/stores/file/lib.php
cache/stores/memcache/lib.php
cache/stores/memcache/tests/memcache_test.php
cache/stores/memcached/lib.php
cache/stores/memcached/tests/memcached_test.php
cache/stores/mongodb/lib.php
cache/stores/mongodb/tests/mongodb_test.php
cache/stores/session/lib.php
cache/stores/static/lib.php
cache/tests/cache_test.php
cache/tests/fixtures/lib.php
cache/tests/fixtures/stores.php
cache/upgrade.txt
enrol/flatfile/lang/en/enrol_flatfile.php
enrol/ldap/lang/en/enrol_ldap.php
enrol/lti/classes/tool_provider.php
enrol/lti/lang/en/enrol_lti.php
enrol/lti/tool.php
enrol/manual/lang/en/enrol_manual.php
enrol/meta/lib.php
enrol/paypal/lang/en/enrol_paypal.php
enrol/self/lang/en/enrol_self.php
install/lang/hy/moodle.php
lang/en/admin.php
lang/en/auth.php
lang/en/role.php
lib/classes/session/manager.php
lib/db/access.php
lib/form/autocomplete.php
lib/form/select.php
lib/form/selectgroups.php
lib/form/selectwithlink.php
lib/outputrenderers.php
lib/testing/classes/util.php
lib/yui/build/moodle-core-maintenancemodetimer/moodle-core-maintenancemodetimer-debug.js
lib/yui/build/moodle-core-maintenancemodetimer/moodle-core-maintenancemodetimer-min.js
lib/yui/build/moodle-core-maintenancemodetimer/moodle-core-maintenancemodetimer.js
lib/yui/src/maintenancemodetimer/js/maintenancemodetimer.js
login/confirm.php
message/classes/api.php
message/externallib.php
message/templates/message_preferences_component.mustache
message/templates/message_preferences_notification_processor.mustache
message/templates/notification_preferences_component.mustache
message/templates/notification_preferences_component_notification.mustache
message/tests/api_test.php
message/tests/externallib_test.php
mod/assign/externallib.php
mod/assign/lang/en/assign.php
mod/lti/lang/en/lti.php
mod/quiz/accessrule/offlineattempts/lang/en/quizaccess_offlineattempts.php
mod/quiz/lang/en/quiz.php
mod/quiz/tests/behat/attempt_redo_questions.feature
question/type/calculated/lang/en/qtype_calculated.php
theme/boost/config.php
theme/boost/lang/en/theme_boost.php
theme/boost/lib.php
theme/boost/pix/screenshot.jpg
theme/boost/scss/moodle/admin.scss
theme/boost/scss/moodle/blocks.scss
theme/boost/scss/moodle/core.scss
theme/boost/scss/moodle/undo.scss
theme/boost/scss/preset-flatly.scss [deleted file]
theme/boost/scss/preset-paper.scss [deleted file]
theme/boost/scss/preset-readable.scss [deleted file]
theme/boost/scss/preset.scss [new file with mode: 0644]
theme/boost/scss/preset/default.scss [moved from theme/boost/scss/preset-default.scss with 100% similarity]
theme/boost/scss/preset/plain.scss [moved from theme/boost/scss/preset-plain.scss with 100% similarity]
theme/boost/settings.php
theme/boost/templates/columns1.mustache
theme/boost/templates/columns2.mustache
theme/boost/templates/core/help_icon.mustache
theme/boost/templates/core_admin/setting_configpasswordunmask.mustache
theme/boost/templates/core_form/element-advcheckbox-inline.mustache
theme/boost/templates/core_form/element-advcheckbox.mustache
theme/boost/templates/core_form/element-checkbox-inline.mustache
theme/boost/templates/core_form/element-checkbox.mustache
theme/boost/templates/core_form/element-radio-inline.mustache
theme/boost/templates/core_form/element-radio.mustache
theme/boost/templates/core_form/element-select-inline.mustache
theme/boost/templates/core_form/element-select.mustache
theme/boost/templates/core_form/element-selectgroups-inline.mustache
theme/boost/templates/core_form/element-selectgroups.mustache
theme/boost/templates/core_form/element-selectwithlink.mustache
theme/boost/templates/maintenance.mustache
theme/boost/thirdpartylibs.xml
theme/boost/version.php
version.php

index 9ad89b7..68293b9 100644 (file)
@@ -72,9 +72,6 @@ theme/boost/amd/src/tab.js
 theme/boost/amd/src/tooltip.js
 theme/boost/amd/src/util.js
 theme/boost/amd/src/tether.js
-theme/boost/scss/preset-flatly.scss
-theme/boost/scss/preset-paper.scss
-theme/boost/scss/preset-readable.scss
 theme/bootstrapbase/less/bootstrap/
 theme/bootstrapbase/javascript/html5shiv.js
 theme/bootstrapbase/amd/src/bootstrap.js
\ No newline at end of file
index f6ac277..383c520 100644 (file)
@@ -73,9 +73,6 @@ theme/boost/amd/src/tab.js
 theme/boost/amd/src/tooltip.js
 theme/boost/amd/src/util.js
 theme/boost/amd/src/tether.js
-theme/boost/scss/preset-flatly.scss
-theme/boost/scss/preset-paper.scss
-theme/boost/scss/preset-readable.scss
 theme/bootstrapbase/less/bootstrap/
 theme/bootstrapbase/javascript/html5shiv.js
 theme/bootstrapbase/amd/src/bootstrap.js
\ No newline at end of file
index bf00ea7..cf7565c 100644 (file)
 }}
 <div class="form-password">
     <span data-passwordunmask="wrapper" data-passwordunmaskid="{{ id }}">
-        <noscript>
-            <!-- Backwards compatability for Behat -->
-            <input  type="password"
-                    name="{{ name }}"
-                    id="{{ id }}"
-                    value="{{ value }}"
-                    size="{{ size }}"
-                    >
-        </noscript>
         <span class="visibleifjs">
             <span data-passwordunmask="editor">
-                <!-- The input in the noscript will be moved here as part of the page load -->
+                <input  type="hidden"
+                        name="{{ name }}"
+                        id="{{ id }}"
+                        value="{{ value }}"
+                        size="{{ size }}"
+                        >
             </span>
             <a href="#" data-passwordunmask="edit" title="{{ edithint }}">
                 <span data-passwordunmask="displayvalue">{{> core_form/element-passwordunmask-fill }}</span>
                 {{# str }} passwordunmaskinstructions, form {{/ str }}
             </span>
         </span>
+        <noscript>
+            <!-- Backwards compatability for Behat -->
+            <input  type="password"
+                    name="{{ name }}"
+                    id="{{ id }}"
+                    value="{{ value }}"
+                    size="{{ size }}"
+                    >
+        </noscript>
     </span>
 </div>
 {{#js}}
index 813b096..9064eb2 100644 (file)
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-$string['competencyscale'] = 'Competency Scale: {$a}';
+$string['competencyscale'] = 'Competency scale: {$a}';
 $string['competencyscaledescription'] = 'Competency scale created by import';
-$string['confirmcolumnmappings'] = 'Confirm the columns mappings';
+$string['confirmcolumnmappings'] = 'Confirm the column mappings';
 $string['confirm'] = 'Confirm';
 $string['csvdelimiter'] = 'CSV delimiter';
-$string['csvdelimiter_help'] = 'CSV delimiter of the CSV file.';
+$string['csvdelimiter_help'] = 'The CSV delimiter is normally a comma.';
 $string['description'] = 'Description';
 $string['descriptionformat'] = 'Description format';
 $string['encoding'] = 'Encoding';
-$string['encoding_help'] = 'Encoding of the CSV file.';
+$string['encoding_help'] = 'The CSV file encoding is usually UTF-8.';
 $string['export'] = 'Export';
-$string['exportid'] = 'Exported id (optional)';
+$string['exportid'] = 'Exported ID (optional)';
 $string['exportnavlink'] = 'Export competency framework';
-$string['idnumber'] = 'Id number';
+$string['idnumber'] = 'ID number';
 $string['importfile'] = 'CSV framework description file';
 $string['import'] = 'Import';
 $string['invalidimportfile'] = 'File format is invalid.';
 $string['isframework'] = 'Is framework';
 $string['noframeworks'] = 'No competency frameworks have been created yet';
-$string['parentidnumber'] = 'Parent id number';
+$string['parentidnumber'] = 'Parent ID number';
 $string['pluginname'] = 'Import competency framework';
-$string['relatedidnumbers'] = 'Cross referenced competency id numbers';
+$string['relatedidnumbers'] = 'Cross-referenced competency ID numbers';
 $string['ruleconfig'] = 'Rule config (optional)';
 $string['ruleoutcome'] = 'Rule outcome (optional)';
 $string['ruletype'] = 'Rule type (optional)';
 $string['scaleconfiguration'] = 'Scale configuration';
 $string['scalevalues'] = 'Scale values';
-$string['shortname'] = 'Shortname';
+$string['shortname'] = 'Short name';
 $string['taxonomy'] = 'Taxonomy';
index f8c0347..441a19a 100644 (file)
@@ -27,12 +27,12 @@ $string['autologinnotallowedtoadmins'] = 'Auto-login is not allowed to site admi
 $string['clickheretolaunchtheapp'] = 'Click here if the app does not open automatically.';
 $string['enablesmartappbanners'] = 'Enable Smart App Banners';
 $string['enablesmartappbanners_desc'] = 'This will display a banner promoting the Moodle Mobile app when visiting the site in Mobile Safari.';
-$string['forcedurlscheme'] = 'The URL scheme allows to open the mobile app from other apps like the browser. Use this setting if you want to allow only your custom branded app to be opened by the browser.';
+$string['forcedurlscheme'] = 'If you want to allow only your custom branded app to be opened via a browser window, then specify its URL scheme here; otherwise leave the field empty.';
 $string['forcedurlscheme_key'] = 'URL scheme';
 $string['httpsrequired'] = 'HTTPS required';
 $string['invalidprivatetoken'] = 'Invalid private token. Token should not be empty or passed via GET parameter.';
 $string['iosappid'] = 'App\'s unique identifier';
-$string['iosappid_desc'] = 'You only need to change this value if you have a custom iOS app';
+$string['iosappid_desc'] = 'This setting may be left as default unless you have a custom iOS app.';
 $string['loginintheapp'] = 'Via the app';
 $string['logininthebrowser'] = 'Via a browser window (for SSO plugins)';
 $string['loginintheembeddedbrowser'] = 'Via an embedded browser (for SSO plugins)';
index 96bc6ea..fec6b60 100644 (file)
@@ -36,6 +36,13 @@ use context;
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 class role extends base {
+    /**
+     * The Site Admin pseudo-role.
+     *
+     * @var ROLE_SITEADMIN int
+     */
+    const ROLE_SITEADMIN = -1;
+
     /**
      * The name of the filter.
      *
@@ -52,7 +59,24 @@ class role extends base {
      *                                  And whose values are the values to display
      */
     public static function get_filter_options() {
-        return role_get_names(null, ROLENAME_ALIAS, true);
+        $allroles = role_get_names(null, ROLENAME_ALIAS);
+
+        $roles = [];
+        foreach ($allroles as $role) {
+            if ($role->archetype === 'guest') {
+                // No point in including the 'guest' role as it isn't possible to show tours to a guest.
+                continue;
+            }
+            $roles[$role->shortname] = $role->localname;
+        }
+
+        // Add the Site Administrator pseudo-role.
+        $roles[self::ROLE_SITEADMIN] = get_string('administrator', 'core');
+
+        // Sort alphabetically too.
+        \core_collator::asort($roles);
+
+        return $roles;
     }
 
     /**
@@ -73,13 +97,14 @@ class role extends base {
             return true;
         }
 
-        if (is_siteadmin()) {
-            return true;
-        }
-
         // Presence within the array is sufficient. Ignore any value.
         $values = array_flip($values);
 
+        if (isset($values[self::ROLE_SITEADMIN]) && is_siteadmin()) {
+            // This tour has been restricted to a role including site admin, and this user is a site admin.
+            return true;
+        }
+
         $cache = \cache::make_from_params(\cache_store::MODE_REQUEST, 'tool_usertours', 'filter_role');
         $cachekey = "{$USER->id}_{$context->id}";
         $userroles = $cache->get($cachekey);
index 90e72ee..31f74bf 100644 (file)
@@ -47,7 +47,7 @@ You can enter a content in the following formats:
     <dt>Moodle Translated string</dt>
     <dd>A value found in a standard Moodle language file in the format identifier,component</dd>
 </dl>';
-$string['cssselector'] = 'CSS Selector';
+$string['cssselector'] = 'CSS selector';
 $string['defaultvalue'] = 'Default ({$a})';
 $string['delay'] = 'Delay before showing the step';
 $string['done'] = 'Done';
@@ -60,12 +60,11 @@ $string['event_tour_ended'] = 'Tour ended';
 $string['event_step_shown'] = 'Step shown';
 $string['exporttour'] = 'Export tour';
 $string['filter_header'] = 'Tour filters';
-$string['filter_help'] = 'Your can choose which conditions your tour will be shown under.
-All of the filters must match for a tour to be shown to that user.';
+$string['filter_help'] = 'Select the conditions under which the tour will be shown. All of the filters must match for a tour to be shown to a user.';
 $string['filter_theme'] = 'Theme';
 $string['filter_theme_help'] = 'Show the tour when the user is using one of the selected themes.';
 $string['filter_role'] = 'Role';
-$string['filter_role_help'] = 'Only show the tour to users with one of the specified roles.';
+$string['filter_role_help'] = 'A tour may be restricted to users with selected roles in the context where the tour is shown. For example, restricting a Dashboard tour to users with the role of student won\'t work if users have the role of student in a course (as is generally the case). A Dashboard tour can only be restricted to users with a system role.';
 $string['importtour'] = 'Import tour';
 $string['left'] = 'Left';
 $string['movestepdown'] = 'Move step down';
@@ -89,7 +88,7 @@ Some example values include:
 * /mod/forum/view.php% - to match the forum discussion list
 * /user/profile.php% - to match the user profile page';
 $string['placement'] = 'Placement';
-$string['pluginname'] = 'User Tours';
+$string['pluginname'] = 'User tours';
 $string['resettouronpage'] = 'Reset user tour on this page';
 $string['right'] = 'Right';
 $string['select_block'] = 'Select a block';
@@ -149,7 +148,7 @@ $string['selecttype'] = 'Select step type';
 $string['sharedtourslink'] = 'Tour repository';
 $string['usertours'] = 'User tours';
 $string['usertours:managetours'] = 'Create, edit, and remove user tours';
-$string['target_selector_targetvalue'] = 'CSS Selectors';
+$string['target_selector_targetvalue'] = 'CSS selectors';
 $string['target_selector_targetvalue_help'] = 'You can use a "CSS Selector" to target almost any element on the page.
 
 CSS Selectors are very powerful and you can easily find parts of the page by building up the selector gradually.
index ade49dd..3f6fed4 100644 (file)
@@ -119,9 +119,9 @@ class tool_usertours_role_filter_testcase extends advanced_testcase {
             }
         }
 
-        // The admin should always be able to view too.
+        // The admin can't view this one either.
         $this->setAdminUser();
-        $this->assertTrue(\tool_usertours\local\filter\role::filter_matches($tour, $context));
+        $this->assertFalse(\tool_usertours\local\filter\role::filter_matches($tour, $context));
     }
 
     /**
@@ -149,9 +149,9 @@ class tool_usertours_role_filter_testcase extends advanced_testcase {
             }
         }
 
-        // The admin should always be able to view too.
+        // The admin can't view this one either.
         $this->setAdminUser();
-        $this->assertTrue(\tool_usertours\local\filter\role::filter_matches($tour, $context));
+        $this->assertFalse(\tool_usertours\local\filter\role::filter_matches($tour, $context));
     }
 
     /**
@@ -181,8 +181,109 @@ class tool_usertours_role_filter_testcase extends advanced_testcase {
             }
         }
 
-        // The admin should always be able to view too.
+        // The admin can't view this one either.
+        $this->setAdminUser();
+        $this->assertFalse(\tool_usertours\local\filter\role::filter_matches($tour, $context));
+    }
+
+    /**
+     * Test the filter_matches function when it is targetted at an admin.
+     */
+    public function test_filter_matches_multiple_role_only_admin() {
+        $context = \context_course::instance($this->course->id);
+
+        $roles = [
+            \tool_usertours\local\filter\role::ROLE_SITEADMIN,
+        ];
+
+        $this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $this->roles['teacher']);
+
+        // Note: No need to persist this tour.
+        $tour = new \tool_usertours\tour();
+        $tour->set_filter_values('role', $roles);
+
+
+        // Note: The role filter does not use the context.
+        foreach ($this->testroles as $role) {
+            $this->setUser($this->$role);
+            $this->assertFalse(\tool_usertours\local\filter\role::filter_matches($tour, $context));
+        }
+
+        // The admin can view this one because it's only aimed at them.
+        $this->setAdminUser();
+        $this->assertTrue(\tool_usertours\local\filter\role::filter_matches($tour, $context));
+    }
+
+    /**
+     * Test the filter_matches function when multiple roles are set, including an admin user.
+     */
+    public function test_filter_matches_multiple_role_including_admin() {
+        $context = \context_course::instance($this->course->id);
+
+        $roles = [
+            \tool_usertours\local\filter\role::ROLE_SITEADMIN,
+            $this->roles['teacher'],
+            $this->roles['editingteacher'],
+        ];
+
+        // Note: No need to persist this tour.
+        $tour = new \tool_usertours\tour();
+        $tour->set_filter_values('role', $roles);
+
+        // Note: The role filter does not use the context.
+        foreach ($this->testroles as $role) {
+            $this->setUser($this->$role);
+            if ($role === 'student') {
+                $this->assertFalse(\tool_usertours\local\filter\role::filter_matches($tour, $context));
+            } else {
+                $this->assertTrue(\tool_usertours\local\filter\role::filter_matches($tour, $context));
+            }
+        }
+
+        // The admin can view this one because it's only aimed at them.
+        $this->setAdminUser();
+        $this->assertTrue(\tool_usertours\local\filter\role::filter_matches($tour, $context));
+    }
+
+    /**
+     * Test the filter_matches function when an admin user has multiple roles.
+     */
+    public function test_filter_matches_multiple_role_admin_user() {
+        global $USER;
+
+        $context = \context_course::instance($this->course->id);
+
+        $roles = [
+            \tool_usertours\local\filter\role::ROLE_SITEADMIN,
+        ];
+
         $this->setAdminUser();
+        $this->getDataGenerator()->enrol_user($USER->id, $this->course->id, $this->roles['student']);
+
+        // Note: No need to persist this tour.
+        $tour = new \tool_usertours\tour();
+        $tour->set_filter_values('role', $roles);
+
+        // The admin can view this one because it's only aimed at them.
         $this->assertTrue(\tool_usertours\local\filter\role::filter_matches($tour, $context));
     }
+
+    /**
+     * Test that the get_filter_options function does not include the guest roles.
+     */
+    public function test_get_filter_options_no_guest_roles() {
+        create_role('Test Role', 'testrole', 'This is a test role', 'guest');
+
+        $allroles = role_get_names(null, ROLENAME_ALIAS);
+        $options = \tool_usertours\local\filter\role::get_filter_options();
+
+        foreach ($allroles as $role) {
+            $hasrole = isset($options[$role->shortname]);
+            if ($role->archetype === 'guest') {
+                $this->assertFalse($hasrole);
+            } else {
+                $this->assertTrue($hasrole);
+            }
+        }
+    }
 }
index 83161a7..008367b 100644 (file)
@@ -9,7 +9,7 @@ $confirm = optional_param('confirm', 0, PARAM_BOOL);
 
 require_login();
 admin_externalpage_setup('userbulk');
-require_capability('moodle/site:readallmessages', context_system::instance());
+require_capability('moodle/site:manageallmessaging', context_system::instance());
 
 $return = $CFG->wwwroot.'/'.$CFG->admin.'/user/user_bulk.php';
 
index 7ca3fb2..6f23523 100644 (file)
@@ -77,7 +77,7 @@ $string['auth_ldap_opt_deref'] = 'Determines how aliases are handled during sear
 $string['auth_ldap_opt_deref_key'] = 'Dereference aliases';
 $string['auth_ldap_passtype'] = 'Specify the format of new or changed passwords in LDAP server.';
 $string['auth_ldap_passtype_key'] = 'Password format';
-$string['auth_ldap_passwdexpire_settings'] = 'LDAP password expiration settings.';
+$string['auth_ldap_passwdexpire_settings'] = 'LDAP password expiration settings';
 $string['auth_ldap_preventpassindb'] = 'Select yes to prevent passwords from being stored in Moodle\'s DB.';
 $string['auth_ldap_preventpassindb_key'] = 'Don\'t cache passwords';
 $string['auth_ldap_search_sub'] = 'Search users from subcontexts.';
@@ -134,7 +134,7 @@ $string['ntlmsso_isdisabled'] = 'NTLM SSO is disabled.';
 $string['ntlmsso_unknowntype'] = 'Unknown ntlmsso type!';
 $string['pagedresultsnotsupp'] = 'LDAP paged results not supported (either your PHP version lacks support or you have configured Moodle to use LDAP protocol version 2)';
 $string['pagesize'] = 'Make sure this value is smaller than your LDAP server result set size limit (the maximum number of entries that can be returned in a single query)';
-$string['pagesize_key'] = 'Page Size';
+$string['pagesize_key'] = 'Page size';
 $string['pluginname'] = 'LDAP server';
 $string['pluginnotenabled'] = 'Plugin not enabled!';
 $string['renamingnotallowed'] = 'User renaming not allowed in LDAP';
index 1b925a4..c11e197 100644 (file)
@@ -262,6 +262,15 @@ class cachestore_dummy extends cache_store {
         return $cache;
     }
 
+    /**
+     * Generates the appropriate configuration required for unit testing.
+     *
+     * @return array Array of unit test configuration data to be used by initialise().
+     */
+    public static function unit_test_configuration() {
+        return [];
+    }
+
     /**
      * Returns the name of this instance.
      * @return string
index ac20bec..4ba6565 100644 (file)
@@ -277,6 +277,9 @@ class cache_factory {
         if (!array_key_exists($name, $this->stores)) {
             // Properties: name, plugin, configuration, class.
             $class = $details['class'];
+            if (!$class::are_requirements_met()) {
+                return false;
+            }
             $store = new $class($details['name'], $details['configuration']);
             $this->stores[$name] = $store;
         }
index c25369e..30f8235 100644 (file)
@@ -502,15 +502,18 @@ class cache_helper {
         $store = $stores[$storename];
         $class = $store['class'];
 
+
+        // We check are_requirements_met although we expect is_ready is going to check as well.
+        if (!$class::are_requirements_met()) {
+            return false;
+        }
         // Found the store: is it ready?
         /* @var cache_store $instance */
         $instance = new $class($store['name'], $store['configuration']);
-        // We check are_requirements_met although we expect is_ready is going to check as well.
-        if (!$instance::are_requirements_met() || !$instance->is_ready()) {
+        if (!$instance->is_ready()) {
             unset($instance);
             return false;
         }
-
         foreach ($config->get_definitions_by_store($storename) as $id => $definition) {
             $definition = cache_definition::load($id, $definition);
             $definitioninstance = clone($instance);
index eec660f..4fcb03f 100644 (file)
@@ -81,15 +81,11 @@ interface cache_store_interface {
     public static function initialise_test_instance(cache_definition $definition);
 
     /**
-     * Initialises a test instance for unit tests.
+     * Generates the appropriate configuration required for unit testing.
      *
-     * This differs from initialise_test_instance in that it doesn't rely on interacting with the config table.
-     *
-     * @since 2.8
-     * @param cache_definition $definition
-     * @return cache_store|false
+     * @return array Array of unit test configuration data to be used by initialise().
      */
-    public static function initialise_unit_test_instance(cache_definition $definition);
+    public static function unit_test_configuration();
 }
 
 /**
@@ -369,20 +365,6 @@ abstract class cache_store implements cache_store_interface {
         return clone($this);
     }
 
-    /**
-     * Initialises a test instance for unit tests.
-     *
-     * This differs from initialise_test_instance in that it doesn't rely on interacting with the config table.
-     * By default however it calls initialise_test_instance to support backwards compatibility.
-     *
-     * @since 2.8
-     * @param cache_definition $definition
-     * @return cache_store|false
-     */
-    public static function initialise_unit_test_instance(cache_definition $definition) {
-        return static::initialise_test_instance($definition);
-    }
-
     /**
      * Can be overridden to return any warnings this store instance should make to the admin.
      *
index e97dd56..90a8a8b 100644 (file)
@@ -684,33 +684,36 @@ abstract class cache_administration_helper extends cache_helper {
         $locks = $instance->get_locks();
         foreach ($stores as $name => $details) {
             $class = $details['class'];
-            $store = new $class($details['name'], $details['configuration']);
+            $store = false;
+            if ($class::are_requirements_met()) {
+                $store = new $class($details['name'], $details['configuration']);
+            }
             $lock = (isset($details['lock'])) ? $locks[$details['lock']] : $instance->get_default_lock();
             $record = array(
                 'name' => $name,
                 'plugin' => $details['plugin'],
                 'default' => $details['default'],
-                'isready' => $store->is_ready(),
+                'isready' => $store ? $store->is_ready() : false,
                 'requirementsmet' => $class::are_requirements_met(),
                 'mappings' => 0,
                 'lock' => $lock,
                 'modes' => array(
                     cache_store::MODE_APPLICATION =>
-                        ($store->get_supported_modes($return) & cache_store::MODE_APPLICATION) == cache_store::MODE_APPLICATION,
+                        ($class::get_supported_modes($return) & cache_store::MODE_APPLICATION) == cache_store::MODE_APPLICATION,
                     cache_store::MODE_SESSION =>
-                        ($store->get_supported_modes($return) & cache_store::MODE_SESSION) == cache_store::MODE_SESSION,
+                        ($class::get_supported_modes($return) & cache_store::MODE_SESSION) == cache_store::MODE_SESSION,
                     cache_store::MODE_REQUEST =>
-                        ($store->get_supported_modes($return) & cache_store::MODE_REQUEST) == cache_store::MODE_REQUEST,
+                        ($class::get_supported_modes($return) & cache_store::MODE_REQUEST) == cache_store::MODE_REQUEST,
                 ),
                 'supports' => array(
-                    'multipleidentifiers' => $store->supports_multiple_identifiers(),
-                    'dataguarantee' => $store->supports_data_guarantee(),
-                    'nativettl' => $store->supports_native_ttl(),
+                    'multipleidentifiers' => $store ? $store->supports_multiple_identifiers() : false,
+                    'dataguarantee' => $store ? $store->supports_data_guarantee() : false,
+                    'nativettl' => $store ? $store->supports_native_ttl() : false,
                     'nativelocking' => ($store instanceof cache_is_lockable),
                     'keyawareness' => ($store instanceof cache_is_key_aware),
                     'searchable' => ($store instanceof cache_is_searchable)
                 ),
-                'warnings' => $store->get_warnings()
+                'warnings' => $store ? $store->get_warnings() : array()
             );
             if (empty($details['default'])) {
                 $return[$name] = $record;
index 95608a6..9bdf82d 100644 (file)
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-$string['clusternotice'] = 'Please be aware that APCu only a suitable choice for single node sites or caches that can be stored locally.
-For more information see <a href="{$a}">Moodle docs</a>';
+$string['clusternotice'] = 'Please be aware that APCu is only a suitable choice for single node sites or caches that can be stored locally.
+For more information, see the <a href="{$a}">APC user cache documentation</a>.';
 $string['notice'] = 'Notice';
-$string['pluginname'] = 'APC User Cache (APCu)';
+$string['pluginname'] = 'APC user cache (APCu)';
 $string['prefix'] = 'Prefix';
 $string['prefix_help'] = 'The above prefix gets used for all keys being stored in this APC store instance. By default the database prefix is used.';
 $string['prefixinvalid'] = 'The prefix you have selected is invalid. You can only use a-z A-Z 0-9-_.';
 $string['prefixnotunique'] = 'The prefix you have selected is not unique. Please choose a unique prefix.';
 $string['testperformance'] = 'Test performance';
-$string['testperformance_desc'] = 'If enabled APCu performance will be included when viewing the Test performance page in the administration block. Enabling this on a production site is not recommended.';
+$string['testperformance_desc'] = 'If enabled, APCu performance will be included when viewing the Test performance page. Enabling this on a production site is not recommended.';
index 27cd2e6..cbb20db 100644 (file)
@@ -369,23 +369,12 @@ class cachestore_apcu extends cache_store implements cache_is_key_aware, cache_i
     }
 
     /**
-     * Generates an instance of the cache store that can be used for testing.
+     * Generates the appropriate configuration required for unit testing.
      *
-     * @param cache_definition $definition
-     * @return cachestore_apcu|false
+     * @return array Array of unit test configuration data to be used by initialise().
      */
-    public static function initialise_unit_test_instance(cache_definition $definition) {
-        if (!self::are_requirements_met()) {
-            return false;
-        }
-
-        $store = new cachestore_apcu('Test APCu', array('prefix' => 'phpunit'));
-        if (!$store->is_ready()) {
-            return false;
-        }
-        $store->initialise($definition);
-
-        return $store;
+    public static function unit_test_configuration() {
+        return array('prefix' => 'phpunit');
     }
 
     /**
@@ -416,4 +405,16 @@ class cachestore_apcu extends cache_store implements cache_is_key_aware, cache_i
         }
         $editform->set_data($data);
     }
+
+    /**
+     * Returns true if this cache store instance is both suitable for testing, and ready for testing.
+     *
+     * Cache stores that support being used as the default store for unit and acceptance testing should
+     * override this function and return true if there requirements have been met.
+     *
+     * @return bool
+     */
+    public static function ready_to_be_used_for_testing() {
+        return true;
+    }
 }
index 36fc1ae..4903d3b 100644 (file)
@@ -57,7 +57,8 @@ class cachestore_apcu_test extends cachestore_tests {
      */
     public function test_cross_application_interaction() {
         $definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_apcu', 'phpunit_test');
-        $instance = cachestore_apcu::initialise_unit_test_instance($definition);
+        $instance = new cachestore_apcu('Test', cachestore_apcu::unit_test_configuration());
+        $instance->initialise($definition);
 
         // Test purge with custom data.
         $this->assertTrue($instance->set('test', 'monster'));
@@ -75,9 +76,12 @@ class cachestore_apcu_test extends cachestore_tests {
 
     public function test_different_caches_have_different_prefixes() {
         $definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_apcu', 'phpunit_test');
-        $instance = cachestore_apcu::initialise_unit_test_instance($definition);
+        $instance = new cachestore_apcu('Test', cachestore_apcu::unit_test_configuration());
+        $instance->initialise($definition);
+
         $definition2 = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_apcu', 'phpunit_test2');
-        $instance2 = cachestore_apcu::initialise_unit_test_instance($definition2);
+        $instance2 = new cachestore_apcu('Test', cachestore_apcu::unit_test_configuration());
+        $instance2->initialise($definition2);
 
         $instance->set('test1', 1);
         $this->assertFalse($instance2->get('test1'));
index 67a6642..91a0839 100644 (file)
@@ -677,6 +677,15 @@ class cachestore_file extends cache_store implements cache_is_key_aware, cache_i
         return $cache;
     }
 
+    /**
+     * Generates the appropriate configuration required for unit testing.
+     *
+     * @return array Array of unit test configuration data to be used by initialise().
+     */
+    public static function unit_test_configuration() {
+        return array();
+    }
+
     /**
      * Writes your madness to a file.
      *
index e4ead7f..6f89d1a 100644 (file)
@@ -582,24 +582,16 @@ class cachestore_memcache extends cache_store implements cache_is_configurable {
     }
 
     /**
-     * Creates a test instance for unit tests if possible.
-     * @param cache_definition $definition
-     * @return bool|cachestore_memcache
+     * Generates the appropriate configuration required for unit testing.
+     *
+     * @return array Array of unit test configuration data to be used by initialise().
      */
-    public static function initialise_unit_test_instance(cache_definition $definition) {
-        if (!self::are_requirements_met()) {
-            return false;
-        }
+    public static function unit_test_configuration() {
+        // If the configuration is not defined correctly, return only the configuration know about.
         if (!defined('TEST_CACHESTORE_MEMCACHE_TESTSERVERS')) {
-            return false;
+            return [];
         }
-        $configuration = array();
-        $configuration['servers'] = explode("\n", TEST_CACHESTORE_MEMCACHE_TESTSERVERS);
-
-        $store = new cachestore_memcache('Test memcache', $configuration);
-        $store->initialise($definition);
-
-        return $store;
+        return ['servers' => explode("\n", TEST_CACHESTORE_MEMCACHE_TESTSERVERS)];
     }
 
     /**
index 0cba975..f88f5fb 100644 (file)
@@ -57,7 +57,8 @@ class cachestore_memcache_test extends cachestore_tests {
         $this->resetAfterTest(true);
 
         $definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_memcache', 'phpunit_test');
-        $instance = cachestore_memcache::initialise_unit_test_instance($definition);
+        $instance = new cachestore_memcache('Memcache Test', cachestore_memcache::unit_test_configuration());
+        $instance->initialise($definition);
 
         if (!$instance) { // Something prevented memcache store to be inited (extension, TEST_CACHESTORE_MEMCACHE_TESTSERVERS...).
             $this->markTestSkipped();
index 84ec315..0c7be7b 100644 (file)
@@ -739,25 +739,16 @@ class cachestore_memcached extends cache_store implements cache_is_configurable
     }
 
     /**
-     * Creates a test instance for unit tests if possible.
-     * @param cache_definition $definition
-     * @return bool|cachestore_memcached
+     * Generates the appropriate configuration required for unit testing.
+     *
+     * @return array Array of unit test configuration data to be used by initialise().
      */
-    public static function initialise_unit_test_instance(cache_definition $definition) {
-        if (!self::are_requirements_met()) {
-            return false;
-        }
+    public static function unit_test_configuration() {
+        // If the configuration is not defined correctly, return only the configuration know about.
         if (!defined('TEST_CACHESTORE_MEMCACHED_TESTSERVERS')) {
-            return false;
+            return [];
         }
-
-        $configuration = array();
-        $configuration['servers'] = explode("\n", TEST_CACHESTORE_MEMCACHED_TESTSERVERS);
-
-        $store = new cachestore_memcached('Test memcached', $configuration);
-        $store->initialise($definition);
-
-        return $store;
+        return ['servers' => explode("\n", TEST_CACHESTORE_MEMCACHED_TESTSERVERS)];
     }
 
     /**
index 6a58844..08ce677 100644 (file)
@@ -61,9 +61,11 @@ class cachestore_memcached_test extends cachestore_tests {
         $this->resetAfterTest(true);
 
         $definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_memcached', 'phpunit_test');
-        $instance = cachestore_memcached::initialise_unit_test_instance($definition);
+        $instance = new cachestore_memcached('Memcached Test', cachestore_memcached::unit_test_configuration());
+        $instance->initialise($definition);
 
-        if (!$instance) { // Something prevented memcached store to be inited (extension, TEST_CACHESTORE_MEMCACHED_TESTSERVERS...).
+        if (!$instance->is_ready()) {
+            // Something prevented memcached store to be inited (extension, TEST_CACHESTORE_MEMCACHED_TESTSERVERS...).
             $this->markTestSkipped();
         }
 
index 641b051..0f1d352 100644 (file)
@@ -571,25 +571,16 @@ class cachestore_mongodb extends cache_store implements cache_is_configurable {
      * @param cache_definition $definition
      * @return false
      */
-    public static function initialise_unit_test_instance(cache_definition $definition) {
-        if (!self::are_requirements_met()) {
-            return false;
-        }
-        if (!defined('TEST_CACHESTORE_MONGODB_TESTSERVER')) {
-            return false;
-        }
-
+    public static function unit_test_configuration() {
         $configuration = array();
-        $configuration['servers'] = explode("\n", TEST_CACHESTORE_MONGODB_TESTSERVER);
         $configuration['usesafe'] = 1;
 
-        $store = new cachestore_mongodb('Test mongodb', $configuration);
-        if (!$store->is_ready()) {
-            return false;
+        // If the configuration is not defined correctly, return only the configuration know about.
+        if (defined('TEST_CACHESTORE_MONGODB_TESTSERVER')) {
+            $configuration['servers'] = explode("\n", TEST_CACHESTORE_MONGODB_TESTSERVER);
         }
-        $store->initialise($definition);
 
-        return $store;
+        return $configuration;
     }
 
     /**
index 5186175..edb7f76 100644 (file)
@@ -56,9 +56,10 @@ class cachestore_mongodb_test extends cachestore_tests {
     public function test_collection_name() {
         // This generates a definition that has a hash starting with a number. MDL-46208.
         $definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_mongodb', 'abc');
-        $instance = cachestore_mongodb::initialise_unit_test_instance($definition);
+        $instance = new cachestore_mongodb('MongoDB_Test', cachestore_mongodb::unit_test_configuration());
+        $instance->initialise($definition);
 
-        if (!$instance) {
+        if (!$instance->is_ready()) {
             $this->markTestSkipped();
         }
 
index d320b8c..f1284f1 100644 (file)
@@ -516,6 +516,14 @@ class cachestore_session extends session_data_store implements cache_is_key_awar
         return $cache;
     }
 
+    /**
+     * Generates the appropriate configuration required for unit testing.
+     *
+     * @return array Array of unit test configuration data to be used by initialise().
+     */
+    public static function unit_test_configuration() {
+        return array();
+    }
     /**
      * Returns the name of this instance.
      * @return string
index d1f6f71..ecf06dd 100644 (file)
@@ -492,6 +492,15 @@ class cachestore_static extends static_data_store implements cache_is_key_aware,
         return $cache;
     }
 
+    /**
+     * Generates the appropriate configuration required for unit testing.
+     *
+     * @return array Array of unit test configuration data to be used by initialise().
+     */
+    public static function unit_test_configuration() {
+        return array();
+    }
+
     /**
      * Returns the name of this instance.
      * @return string
index 255cbf3..eedc37d 100644 (file)
@@ -1315,8 +1315,10 @@ class core_cache_testcase extends advanced_testcase {
 
         $configfile = $CFG->dataroot.'/muc/config.php';
 
-        // That's right, we're deleting the config file.
-        $this->assertTrue(@unlink($configfile));
+        // The config file will not exist yet as we've not done anything with the cache.
+        // reset_all_data removes the file and without a call to create a configuration it doesn't exist
+        // as yet.
+        $this->assertFileNotExists($configfile);
 
         // Disable the cache
         cache_phpunit_factory::phpunit_disable();
index 1bdf7d7..c6b405b 100644 (file)
@@ -73,13 +73,13 @@ class cache_config_testing extends cache_config_writer {
             if (class_exists($class) && $class::ready_to_be_used_for_testing()) {
                 /* @var cache_store $class */
                 $writer->configstores['test_application'] = array(
-                    'use_test_store' => true,
                     'name' => 'test_application',
                     'plugin' => $expectedstore,
-                    'alt' => $writer->configstores[$defaultapplication],
                     'modes' => $class::get_supported_modes(),
-                    'features' => $class::get_supported_features()
+                    'features' => $class::get_supported_features(),
+                    'configuration' => $class::unit_test_configuration()
                 );
+
                 $defaultapplication = 'test_application';
             }
         }
@@ -535,47 +535,4 @@ class cache_phpunit_factory extends cache_factory {
     public static function phpunit_disable() {
         parent::disable();
     }
-
-    /**
-     * @var bool Whether the warning notice about alternative cache store used has been displayed.
-     */
-    protected $altcachestorenotice = false;
-
-    /**
-     * Creates a store instance given its name and configuration.
-     *
-     * If the store has already been instantiated then the original object will be returned. (reused)
-     *
-     * @param string $name The name of the store (must be unique remember)
-     * @param array $details
-     * @param cache_definition $definition The definition to instantiate it for.
-     * @return boolean|cache_store
-     */
-    public function create_store_from_config($name, array $details, cache_definition $definition) {
-
-        if (isset($details['use_test_store'])) {
-            // name, plugin, alt
-            $class = 'cachestore_'.$details['plugin'];
-            $method = 'initialise_unit_test_instance';
-            if (class_exists($class) && method_exists($class, $method)) {
-                $instance = $class::$method($definition);
-
-                if ($instance) {
-                    return $instance;
-                }
-            }
-
-            // Notify user that alternative store is being used, so action can be taken.
-            if (!$this->altcachestorenotice) {
-                echo PHP_EOL . "++ WARNING: " . 'Failed to use "' . $details['plugin'] . '" cache store, alt "' .
-                    $details['alt']['plugin'] . '" cache store is used.' . PHP_EOL . PHP_EOL;
-                $this->altcachestorenotice = true;
-            }
-            $details = $details['alt'];
-            $details['class'] = 'cachestore_'.$details['plugin'];
-            $name = $details['name'];
-        }
-
-        return parent::create_store_from_config($name, $details, $definition);
-    }
 }
\ No newline at end of file
index 1dbe75a..56f94e7 100644 (file)
@@ -43,18 +43,28 @@ abstract class cachestore_tests extends advanced_testcase {
     abstract protected function get_class_name();
 
     /**
-     * Run the unit tests for the store.
+     * Sets up the fixture, for example, open a network connection.
+     * This method is called before a test is executed.
      */
-    public function test_test_instance() {
+    public function setUp() {
         $class = $this->get_class_name();
-        if (!class_exists($class) || !method_exists($class, 'initialise_test_instance') || !$class::are_requirements_met()) {
+        if (!class_exists($class) || !$class::are_requirements_met()) {
             $this->markTestSkipped('Could not test '.$class.'. Requirements are not met.');
         }
+        parent::setUp();
+    }
+    /**
+     * Run the unit tests for the store.
+     */
+    public function test_test_instance() {
+        $class = $this->get_class_name();
 
         $modes = $class::get_supported_modes();
         if ($modes & cache_store::MODE_APPLICATION) {
             $definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, $class, 'phpunit_test');
-            $instance = $class::initialise_unit_test_instance($definition);
+            $instance = new $class($class.'_test', $class::unit_test_configuration());
+            $instance->initialise($definition);
+
             if (!$instance) {
                 $this->markTestSkipped('Could not test '.$class.'. No test instance configured for application caches.');
             } else {
@@ -63,7 +73,9 @@ abstract class cachestore_tests extends advanced_testcase {
         }
         if ($modes & cache_store::MODE_SESSION) {
             $definition = cache_definition::load_adhoc(cache_store::MODE_SESSION, $class, 'phpunit_test');
-            $instance = $class::initialise_unit_test_instance($definition);
+            $instance = new $class($class.'_test', $class::unit_test_configuration());
+            $instance->initialise($definition);
+
             if (!$instance) {
                 $this->markTestSkipped('Could not test '.$class.'. No test instance configured for session caches.');
             } else {
@@ -72,7 +84,9 @@ abstract class cachestore_tests extends advanced_testcase {
         }
         if ($modes & cache_store::MODE_REQUEST) {
             $definition = cache_definition::load_adhoc(cache_store::MODE_REQUEST, $class, 'phpunit_test');
-            $instance = $class::initialise_unit_test_instance($definition);
+            $instance = new $class($class.'_test', $class::unit_test_configuration());
+            $instance->initialise($definition);
+
             if (!$instance) {
                 $this->markTestSkipped('Could not test '.$class.'. No test instance configured for request caches.');
             } else {
index c2649c0..e995cff 100644 (file)
@@ -13,6 +13,8 @@ Information provided here is intended especially for developers.
   - cache_store::cleanup()
 * cachestore_dummy::cleanup() has been deprecated.
 * cachestore_dummy::instance_deleted() implemented in lieu of cachestore_dummy::cleanup().
+* Added cache_store::unit_test_configuration() to calculate unit testing configuration.
+* Remove cache_store:initialise_unit_test_instance() as it is incompatible with cache_helper purge functions.
 
 === 3.1 ===
 * Cache stores has a new feature DEREFERENCES_OBJECTS.
index a1c9922..8861928 100644 (file)
@@ -23,7 +23,7 @@
  */
 
 $string['encoding'] = 'File encoding';
-$string['expiredaction'] = 'Enrolment expiration action';
+$string['expiredaction'] = 'Enrolment expiry action';
 $string['expiredaction_help'] = 'Select action to carry out when user enrolment expires. Please note that some user data and settings are purged from course during course unenrolment.';
 $string['filelockedmail'] = 'The text file you are using for file-based enrolments ({$a}) can not be deleted by the cron process.  This usually means the permissions are wrong on it.  Please fix the permissions so that Moodle can delete the file, otherwise it might be processed repeatedly.';
 $string['filelockedmailsubject'] = 'Important error: Enrolment file';
index 70a3d3e..5d8b877 100644 (file)
@@ -29,7 +29,7 @@ $string['autocreate'] = '<p>Courses can be created automatically if there are en
 $string['autocreate_key'] = 'Auto create';
 $string['autocreation_settings'] = 'Automatic course creation settings';
 $string['autoupdate_settings'] = 'Automatic course update settings';
-$string['autoupdate_settings_desc'] = '<p>Select fields to update when synchronization script is running (enrol/ldap/cli/sync.php).</p><p>When at least one field is selected an update will occur.</p>';
+$string['autoupdate_settings_desc'] = '<p>Select fields to update when synchronisation script is running (enrol/ldap/cli/sync.php).</p><p>When at least one field is selected an update will occur.</p>';
 $string['bind_dn'] = 'If you want to use a bind user to search users, specify it here. Someting like \'cn=ldapuser,ou=public,o=org\'';
 $string['bind_dn_key'] = 'Bind user distinguished name';
 $string['bind_pw'] = 'Password for the bind user';
@@ -47,7 +47,7 @@ $string['couldnotfinduser'] = "Could not find user '{\$a}', skipping\n";
 $string['coursenotexistskip'] = "Course '{\$a}' does not exist and autocreation disabled, skipping\n";
 $string['course_fullname'] = 'Optional: LDAP attribute to get the full name from';
 $string['course_fullname_key'] = 'Full name';
-$string['course_fullname_updateonsync'] = 'Update full name during synchronization script';
+$string['course_fullname_updateonsync'] = 'Update full name during synchronisation script';
 $string['course_fullname_updateonsync_key'] = 'Update full name';
 $string['course_idnumber'] = 'LDAP attribute to get the course ID number from. Usually \'cn\' or \'uid\'.';
 $string['course_idnumber_key'] = 'ID number';
@@ -56,11 +56,11 @@ $string['course_search_sub_key'] = 'Search subcontexts';
 $string['course_settings'] = 'Course enrolment settings';
 $string['course_shortname'] = 'Optional: LDAP attribute to get the shortname from';
 $string['course_shortname_key'] = 'Short name';
-$string['course_shortname_updateonsync'] = 'Update short name during synchronization script';
+$string['course_shortname_updateonsync'] = 'Update short name during synchronisation script';
 $string['course_shortname_updateonsync_key'] = 'Update short name';
 $string['course_summary'] = 'Optional: LDAP attribute to get the summary from';
 $string['course_summary_key'] = 'Summary';
-$string['course_summary_updateonsync'] = 'Update summary during synchronization script';
+$string['course_summary_updateonsync'] = 'Update summary during synchronisation script';
 $string['course_summary_updateonsync_key'] = 'Update summary';
 $string['createcourseextid'] = 'CREATE User enrolled to a nonexistant course \'{$a->courseextid}\'';
 $string['createnotcourseextid'] = 'User enrolled to a nonexistant course \'{$a->courseextid}\'';
index 0ceec89..c832b1b 100644 (file)
@@ -287,6 +287,9 @@ class tool_provider extends ToolProvider {
             helper::update_user_profile_image($user->id, $image);
         }
 
+        // Check if we need to force the page layout to embedded.
+        $isforceembed = $this->resourceLink->getSetting('custom_force_embed') == 1;
+
         // Check if we are an instructor.
         $isinstructor = $this->user->isStaff() || $this->user->isAdmin();
 
@@ -294,25 +297,27 @@ class tool_provider extends ToolProvider {
             $courseid = $context->instanceid;
             $urltogo = new moodle_url('/course/view.php', ['id' => $courseid]);
 
-            // May still be set from previous session, so unset it.
-            unset($SESSION->forcepagelayout);
         } else if ($context->contextlevel == CONTEXT_MODULE) {
             $cm = get_coursemodule_from_id(false, $context->instanceid, 0, false, MUST_EXIST);
             $urltogo = new moodle_url('/mod/' . $cm->modname . '/view.php', ['id' => $cm->id]);
 
             // If we are a student in the course module context we do not want to display blocks.
-            if (!$isinstructor) {
-                // Force the page layout.
-                $SESSION->forcepagelayout = 'embedded';
-            } else {
-                // May still be set from previous session, so unset it.
-                unset($SESSION->forcepagelayout);
+            if (!$isforceembed && !$isinstructor) {
+                $isforceembed = true;
             }
         } else {
             print_error('invalidcontext');
             exit();
         }
 
+        // Force page layout to embedded if necessary.
+        if ($isforceembed) {
+            $SESSION->forcepagelayout = 'embedded';
+        } else {
+            // May still be set from previous session, so unset it.
+            unset($SESSION->forcepagelayout);
+        }
+
         // Enrol the user in the course with no role.
         $result = helper::enrol_user($tool, $user->id);
 
index 7b126b8..3cf57e8 100644 (file)
@@ -47,7 +47,9 @@ $string['maxenrolled'] = 'Maximum enrolled users';
 $string['maxenrolled_help'] = 'The maximum number of remote users who can access the tool. If set to zero, the number of enrolled users is unlimited.';
 $string['maxenrolledreached'] = 'The maximum number of remote users allowed to access the tool has been reached.';
 $string['membersync'] = 'User synchronisation';
-$string['membersync_help'] = 'Whether an account is created for each remote user and the user is enrolled in this course.';
+$string['membersync_help'] = 'Whether a scheduled task synchronises enrolled users in the remote system with enrolments in this course, creating an account for each remote user as necessary, and enrolling or unenrolling them as required.
+
+If set to no, at the moment when a remote user accesses the tool, an account will be created for them and they will be automatically enrolled.';
 $string['membersyncmode'] = 'User synchronisation mode';
 $string['membersyncmode_help'] = 'Whether remote users should be enrolled and/or unenrolled from this course.';
 $string['membersyncmodeenrolandunenrol'] = 'Enrol new and unenrol missing users';
index a018532..f3436cf 100644 (file)
@@ -74,7 +74,7 @@ if ($ltiversion === \IMSGlobal\LTI\ToolProvider\ToolProvider::LTI_VERSION1) {
     $consumer->ltiVersion = \IMSGlobal\LTI\ToolProvider\ToolProvider::LTI_VERSION1;
     // For LTIv1, set the tool secret as the consumer secret.
     $consumer->secret = $tool->secret;
-    $consumer->name = optional_param('tool_consumer_instance_name', null, PARAM_TEXT);
+    $consumer->name = optional_param('tool_consumer_instance_name', '', PARAM_TEXT);
     $consumer->consumerName = $consumer->name;
     $consumer->consumerGuid = optional_param('tool_consumer_instance_guid', null, PARAM_TEXT);
     $consumer->consumerVersion = optional_param('tool_consumer_info_version', null, PARAM_TEXT);
index b325f4a..2b3c572 100644 (file)
@@ -37,7 +37,7 @@ $string['deleteselectedusers'] = 'Delete selected user enrolments';
 $string['editselectedusers'] = 'Edit selected user enrolments';
 $string['enrolledincourserole'] = 'Enrolled in "{$a->course}" as "{$a->role}"';
 $string['enrolusers'] = 'Enrol users';
-$string['expiredaction'] = 'Enrolment expiration action';
+$string['expiredaction'] = 'Enrolment expiry action';
 $string['expiredaction_help'] = 'Select action to carry out when user enrolment expires. Please note that some user data and settings are purged from course during course unenrolment.';
 $string['expirymessageenrollersubject'] = 'Enrolment expiry notification';
 $string['expirymessageenrollerbody'] = 'Enrolment in the course \'{$a->course}\' will expire within the next {$a->threshold} for the following users:
index e563b60..1415f57 100644 (file)
@@ -332,7 +332,7 @@ class enrol_meta_plugin extends enrol_plugin {
 
         $options = array(
             'requiredcapabilities' => array('enrol/meta:selectaslinked'),
-            'multiple' => true,
+            'multiple' => empty($instance->id),  // We only accept multiple values on creation.
             'exclude' => $excludelist
         );
         $mform->addElement('course', 'customint1', get_string('linkedcourse', 'enrol_meta'), $options);
@@ -362,15 +362,24 @@ class enrol_meta_plugin extends enrol_plugin {
         $c = false;
 
         if (!empty($data['customint1'])) {
-            foreach ($data['customint1'] as $courseid) {
+            $courses = is_array($data['customint1']) ? $data['customint1'] : [$data['customint1']];
+            foreach ($courses as $courseid) {
                 $c = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
                 $coursecontext = context_course::instance($c->id);
-                $existing = $DB->get_records('enrol', array('enrol' => 'meta', 'courseid' => $thiscourseid), '', 'customint1, id');
+
+                $sqlexists = 'enrol = :meta AND courseid = :currentcourseid AND customint1 = :courseid AND id != :id';
+                $existing = $DB->record_exists_select('enrol', $sqlexists, [
+                    'meta' => 'meta',
+                    'currentcourseid' => $thiscourseid,
+                    'courseid' => $c->id,
+                    'id' => $instance->id
+                ]);
+
                 if (!$c->visible and !has_capability('moodle/course:viewhiddencourses', $coursecontext)) {
                     $errors['customint1'] = get_string('error');
                 } else if (!has_capability('enrol/meta:selectaslinked', $coursecontext)) {
                     $errors['customint1'] = get_string('error');
-                } else if ($c->id == SITEID or $c->id == $thiscourseid or isset($existing[$c->id])) {
+                } else if ($c->id == SITEID or $c->id == $thiscourseid or $existing) {
                     $errors['customint1'] = get_string('error');
                 }
             }
index e3f8e0b..aa9c7a5 100644 (file)
@@ -39,7 +39,7 @@ $string['enrolperiod_desc'] = 'Default length of time that the enrolment is vali
 $string['enrolperiod_help'] = 'Length of time that the enrolment is valid, starting with the moment the user is enrolled. If disabled, the enrolment duration will be unlimited.';
 $string['enrolstartdate'] = 'Start date';
 $string['enrolstartdate_help'] = 'If enabled, users can be enrolled from this date onward only.';
-$string['expiredaction'] = 'Enrolment expiration action';
+$string['expiredaction'] = 'Enrolment expiry action';
 $string['expiredaction_help'] = 'Select action to carry out when user enrolment expires. Please note that some user data and settings are purged from course during course unenrolment.';
 $string['mailadmins'] = 'Notify admin';
 $string['mailstudents'] = 'Notify students';
index 480489f..583955a 100644 (file)
@@ -48,7 +48,7 @@ $string['enrolperiod_desc'] = 'Default length of time that the enrolment is vali
 $string['enrolperiod_help'] = 'Length of time that the enrolment is valid, starting with the moment the user enrols themselves. If disabled, the enrolment duration will be unlimited.';
 $string['enrolstartdate'] = 'Start date';
 $string['enrolstartdate_help'] = 'If enabled, users can enrol themselves from this date onward only.';
-$string['expiredaction'] = 'Enrolment expiration action';
+$string['expiredaction'] = 'Enrolment expiry action';
 $string['expiredaction_help'] = 'Select action to carry out when user enrolment expires. Please note that some user data and settings are purged from course during course unenrolment.';
 $string['expirymessageenrollersubject'] = 'Self enrolment expiry notification';
 $string['expirymessageenrollerbody'] = 'Self enrolment in the course \'{$a->course}\' will expire within the next {$a->threshold} for the following users:
index 3aa527f..acd942f 100644 (file)
@@ -31,6 +31,7 @@
 defined('MOODLE_INTERNAL') || die();
 
 $string['language'] = 'Լեզու';
+$string['moodlelogo'] = 'Moodle-ի լոգոտիպ';
 $string['next'] = 'Հաջորդը';
 $string['previous'] = 'Նախորդը';
 $string['reload'] = 'Վերաբեռնել';
index 7f23471..9fd0882 100644 (file)
@@ -1083,7 +1083,7 @@ $string['timezoneisforcedto'] = 'Force all users to use';
 $string['timezonenotforced'] = 'Users can choose their own timezone';
 $string['timezonephpdefault'] = 'Default PHP timezone ({$a})';
 $string['timezoneserver'] = 'Server timezone ({$a})';
-$string['tlswarning'] = 'No PHP/cURL extension with TLSv1.2 support has been detected. Some services may not work. It is strongly recommentd that you upgrade your TLS libraries.';
+$string['tlswarning'] = 'No PHP/cURL extension with TLSv1.2 support has been detected. Some services may not work. It is strongly recommended to upgrade your TLS libraries.';
 $string['tokenizerrecommended'] = 'Installing the optional PHP Tokenizer extension is recommended -- it improves Moodle Networking functionality.';
 $string['tools'] = 'Admin tools';
 $string['toolsmanage'] = 'Manage admin tools';
index f540be7..fdebdc1 100644 (file)
@@ -47,13 +47,13 @@ $string['auth_passwordwillexpire'] = 'Your password will expire in {$a} days. Do
 $string['auth_remove_delete'] = 'Full delete internal';
 $string['auth_remove_keep'] = 'Keep internal';
 $string['auth_remove_suspend'] = 'Suspend internal';
-$string['auth_remove_user'] = 'Specify what to do with internal user account during mass synchronization when user was removed from external source. Only suspended users are automatically revived if they reappear in ext source.';
+$string['auth_remove_user'] = 'Specify what to do with internal user account during mass synchronisation when user was removed from external source. Only suspended users are automatically restored if they reappear in the external source.';
 $string['auth_remove_user_key'] = 'Removed ext user';
 $string['auth_sync_suspended']  = 'When enabled, the suspended attribute will be used to update the local user account\'s suspension status.';
-$string['auth_sync_suspended_key'] = 'Synchronize local user suspension status';
-$string['auth_sync_script'] = 'User account syncronisation';
+$string['auth_sync_suspended_key'] = 'Synchronise local user suspension status';
+$string['auth_sync_script'] = 'User account synchronisation';
 $string['auth_updatelocal'] = 'Update local';
-$string['auth_updatelocal_expl'] = '<p><b>Update local:</b> If enabled, the field will be updated (from external auth) every time the user logs in or there is a user synchronization. Fields set to update locally should be locked.</p>';
+$string['auth_updatelocal_expl'] = '<p><b>Update local:</b> If enabled, the field will be updated (from external auth) every time the user logs in or there is a user synchronisation. Fields set to update locally should be locked.</p>';
 $string['auth_updateremote'] = 'Update external';
 $string['auth_updateremote_expl'] = '<p><b>Update external:</b> If enabled, the external auth will be updated when the user record is updated. Fields should be unlocked to allow edits.</p>';
 $string['auth_updateremote_ldap'] = '<p><b>Note:</b> Updating external LDAP data requires that you set binddn and bindpw to a bind-user with editing privileges to all the user records. It currently does not preserve multi-valued attributes, and will remove extra values on update. </p>';
index 27b8921..6ea99fe 100644 (file)
@@ -393,7 +393,8 @@ $string['site:doanything'] = 'Allowed to do everything';
 $string['site:doclinks'] = 'Show links to offsite docs';
 $string['site:forcelanguage'] = 'Override course language';
 $string['site:import'] = 'Import other courses into a course';
-$string['site:maintenanceaccess'] = 'Allowed access when maintenance mode is enabled.';
+$string['site:maintenanceaccess'] = 'Access site while in maintenance mode';
+$string['site:manageallmessaging'] = 'Can perform all messaging actions on site';
 $string['site:manageblocks'] = 'Manage blocks on a page';
 $string['site:mnetloginfromremote'] = 'Login from a remote application via MNet';
 $string['site:mnetlogintoremote'] = 'Roam to a remote application via MNet';
index c75e12b..4d0386b 100644 (file)
@@ -252,12 +252,7 @@ class manager {
 
         // Set configuration.
         session_name($sessionname);
-        // The session cookie expiry time cannot be extended so this needs to be set to a reasonable period, longer than
-        // the sessiontimeout.
-        // This ensures that the cookie is unlikely to timeout before the session does.
-        $sessionlifetime = $CFG->sessiontimeout + WEEKSECS;
-        session_set_cookie_params($sessionlifetime, $CFG->sessioncookiepath, $CFG->sessioncookiedomain,
-                $cookiesecure, $CFG->cookiehttponly);
+        session_set_cookie_params(0, $CFG->sessioncookiepath, $CFG->sessioncookiedomain, $cookiesecure, $CFG->cookiehttponly);
         ini_set('session.use_trans_sid', '0');
         ini_set('session.use_only_cookies', '1');
         ini_set('session.hash_function', '0');        // For now MD5 - we do not have room for sha-1 in sessions table.
index f371558..4f529bd 100644 (file)
@@ -77,6 +77,17 @@ $capabilities = array(
         )
     ),
 
+    'moodle/site:manageallmessaging' => array(
+
+        'riskbitmask' => RISK_PERSONAL,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_SYSTEM,
+        'archetypes' => array(
+            'manager' => CAP_ALLOW
+        )
+    ),
+
     'moodle/site:deleteanymessage' => array(
 
         'riskbitmask' => RISK_DATALOSS,
index 787db39..0e501ab 100644 (file)
@@ -121,8 +121,11 @@ class MoodleQuickForm_autocomplete extends MoodleQuickForm_select {
         // Enhance the select with javascript.
         $this->_generateId();
         $id = $this->getAttribute('id');
-        $PAGE->requires->js_call_amd('core/form-autocomplete', 'enhance', $params = array('#' . $id, $this->tags, $this->ajax,
-            $this->placeholder, $this->casesensitive, $this->showsuggestions, $this->noselectionstring));
+
+        if (!$this->isFrozen()) {
+            $PAGE->requires->js_call_amd('core/form-autocomplete', 'enhance', $params = array('#' . $id, $this->tags, $this->ajax,
+                $this->placeholder, $this->casesensitive, $this->showsuggestions, $this->noselectionstring));
+        }
 
         return parent::toHTML();
     }
index d0a03dc..e0f8cf9 100644 (file)
@@ -200,6 +200,8 @@ class MoodleQuickForm_select extends HTML_QuickForm_select implements templatabl
         $context = $this->export_for_template_base($output);
 
         $options = [];
+        // Standard option attributes.
+        $standardoptionattributes = ['text', 'value', 'selected', 'disabled'];
         foreach ($this->_options as $option) {
             if (is_array($this->_values) && in_array( (string) $option['attr']['value'], $this->_values)) {
                 $this->_updateAttrArray($option['attr'], ['selected' => 'selected']);
@@ -207,8 +209,17 @@ class MoodleQuickForm_select extends HTML_QuickForm_select implements templatabl
             $o = [
                 'text' => $option['text'],
                 'value' => $option['attr']['value'],
-                'selected' => !empty($option['attr']['selected'])
+                'selected' => !empty($option['attr']['selected']),
+                'disabled' => !empty($option['attr']['disabled']),
             ];
+            // Set other attributes.
+            $otheroptionattributes = [];
+            foreach ($option['attr'] as $attr => $value) {
+                if (!in_array($attr, $standardoptionattributes) && $attr != 'class' && !is_object($value)) {
+                    $otheroptionattributes[] = $attr . '="' . s($value) . '"';
+                }
+            }
+            $o['optionattributes'] = implode(' ', $otheroptionattributes);
             $options[] = $o;
         }
         $context['options'] = $options;
index ab547cf..9ed4d05 100644 (file)
@@ -522,6 +522,8 @@ class MoodleQuickForm_selectgroups extends HTML_QuickForm_element implements tem
             ];
         }
 
+        // Standard option attributes.
+        $standardoptionattributes = ['text', 'value', 'selected', 'disabled'];
         foreach ($this->_optGroups as $group) {
             $options = [];
 
@@ -533,6 +535,15 @@ class MoodleQuickForm_selectgroups extends HTML_QuickForm_element implements tem
                     $o['selected'] = false;
                 }
                 $o['text'] = $option['text'];
+                $o['disabled'] = !empty($option['attr']['disabled']);
+                // Set other attributes.
+                $otheroptionattributes = [];
+                foreach ($option['attr'] as $attr => $value) {
+                    if (!in_array($attr, $standardoptionattributes) && $attr != 'class' && !is_object($value)) {
+                        $otheroptionattributes[] = $attr . '="' . s($value) . '"';
+                    }
+                }
+                $o['optionattributes'] = implode(' ', $otheroptionattributes);
                 $options[] = $o;
             }
 
index 1643e6f..fc4a915 100644 (file)
@@ -231,6 +231,8 @@ class MoodleQuickForm_selectwithlink extends HTML_QuickForm_select implements te
         $context = $this->export_for_template_base($output);
 
         $options = [];
+        // Standard option attributes.
+        $standardoptionattributes = ['text', 'value', 'selected', 'disabled'];
         foreach ($this->_options as $option) {
             if (is_array($this->_values) && in_array( (string) $option['attr']['value'], $this->_values)) {
                 $this->_updateAttrArray($option['attr'], ['selected' => 'selected']);
@@ -238,8 +240,17 @@ class MoodleQuickForm_selectwithlink extends HTML_QuickForm_select implements te
             $o = [
                 'text' => $option['text'],
                 'value' => $option['attr']['value'],
-                'selected' => !empty($option['attr']['selected'])
+                'selected' => !empty($option['attr']['selected']),
+                'disabled' => !empty($option['attr']['disabled']),
             ];
+            // Set other attributes.
+            $otheroptionattributes = [];
+            foreach ($option['attr'] as $attr => $value) {
+                if (!in_array($attr, $standardoptionattributes) && $attr != 'class' && !is_object($value)) {
+                    $otheroptionattributes[] = $attr . '="' . s($value) . '"';
+                }
+            }
+            $o['optionattributes'] = implode(' ', $otheroptionattributes);
             $options[] = $o;
         }
         $context['options'] = $options;
index 9ac6a65..5f6c98f 100644 (file)
@@ -656,8 +656,8 @@ class core_renderer extends renderer_base {
         if (isset($CFG->maintenance_later) and $CFG->maintenance_later > time()) {
             $timeleft = $CFG->maintenance_later - time();
             // If timeleft less than 30 sec, set the class on block to error to highlight.
-            $errorclass = ($timeleft < 30) ? 'error' : 'warning';
-            $output .= $this->box_start($errorclass . ' moodle-has-zindex maintenancewarning');
+            $errorclass = ($timeleft < 30) ? 'alert-error alert-danger' : 'alert-warning';
+            $output .= $this->box_start($errorclass . ' moodle-has-zindex maintenancewarning m-a-1 alert');
             $a = new stdClass();
             $a->hour = (int)($timeleft / 3600);
             $a->min = (int)(($timeleft / 60) % 60);
index f3c04a3..4a8b682 100644 (file)
@@ -814,12 +814,13 @@ abstract class testing_util {
         make_temp_directory('');
         make_cache_directory('');
         make_localcache_directory('');
-        // Reset the cache API so that it recreates it's required directories as well.
-        cache_factory::reset();
-        // Purge all data from the caches. This is required for consistency.
+        // Purge all data from the caches. This is required for consistency between tests.
         // Any file caches that happened to be within the data root will have already been clearer (because we just deleted cache)
-        // and now we will purge any other caches as well.
+        // and now we will purge any other caches as well.  This must be done before the cache_factory::reset() as that
+        // removes all definitions of caches and purge does not have valid caches to operate on.
         cache_helper::purge_all();
+        // Reset the cache API so that it recreates it's required directories as well.
+        cache_factory::reset();
     }
 
     /**
index 430f159..434bb70 100644 (file)
Binary files a/lib/yui/build/moodle-core-maintenancemodetimer/moodle-core-maintenancemodetimer-debug.js and b/lib/yui/build/moodle-core-maintenancemodetimer/moodle-core-maintenancemodetimer-debug.js differ
index 9435047..1a107a0 100644 (file)
Binary files a/lib/yui/build/moodle-core-maintenancemodetimer/moodle-core-maintenancemodetimer-min.js and b/lib/yui/build/moodle-core-maintenancemodetimer/moodle-core-maintenancemodetimer-min.js differ
index 430f159..434bb70 100644 (file)
Binary files a/lib/yui/build/moodle-core-maintenancemodetimer/moodle-core-maintenancemodetimer.js and b/lib/yui/build/moodle-core-maintenancemodetimer/moodle-core-maintenancemodetimer.js differ
index 9d4899d..a35d518 100644 (file)
@@ -47,11 +47,13 @@ Y.extend(MAINTENANCEMODETIMER, Y.Base, {
         }
         // Set error class to highlight the importance.
         if (this.timeleftinsec < 30) {
-            this.maintenancenode.addClass('error')
-                    .removeClass('warning');
+            this.maintenancenode.addClass('alert-error')
+                    .addClass('alert-danger')
+                    .removeClass('alert-warning');
         } else {
-            this.maintenancenode.addClass('warning')
-                    .removeClass('error');
+            this.maintenancenode.addClass('alert-warning')
+                    .removeClass('alert-error')
+                    .removeClass('alert-danger');
         }
     }
 });
index 83818bb..cd44e0b 100644 (file)
@@ -25,6 +25,7 @@
  */
 
 require('../config.php');
+require_once($CFG->libdir . '/authlib.php');
 
 $data = optional_param('data', '', PARAM_RAW);  // Formatted as:  secret/username
 
index 23f0feb..4398fba 100644 (file)
@@ -196,14 +196,19 @@ class api {
         }
 
         // Now, let's get the courses.
+        // Make sure to limit searches to enrolled courses.
+        $enrolledcourses = enrol_get_my_courses(array('id', 'cacherev'));
         $courses = array();
-        if ($arrcourses = \coursecat::search_courses(array('search' => $search), array('limit' => $limitnum))) {
+        if ($arrcourses = \coursecat::search_courses(array('search' => $search), array('limit' => $limitnum),
+                array('moodle/course:viewparticipants'))) {
             foreach ($arrcourses as $course) {
-                $data = new \stdClass();
-                $data->id = $course->id;
-                $data->shortname = $course->shortname;
-                $data->fullname = $course->fullname;
-                $courses[] = $data;
+                if (isset($enrolledcourses[$course->id])) {
+                    $data = new \stdClass();
+                    $data->id = $course->id;
+                    $data->shortname = $course->shortname;
+                    $data->fullname = $course->fullname;
+                    $courses[] = $data;
+                }
             }
         }
 
index a22831c..e86f581 100644 (file)
@@ -214,13 +214,26 @@ class core_message_external extends external_api {
      * @since Moodle 2.5
      */
     public static function create_contacts($userids, $userid = 0) {
-        global $CFG;
+        global $CFG, $USER;
 
         // Check if messaging is enabled.
         if (empty($CFG->messaging)) {
             throw new moodle_exception('disabled', 'message');
         }
 
+        if (empty($userid)) {
+            $userid = $USER->id;
+        }
+
+        // Validate context.
+        $context = context_system::instance();
+        self::validate_context($context);
+
+        $capability = 'moodle/site:manageallmessaging';
+        if (($USER->id != $userid) && !has_capability($capability, $context)) {
+            throw new required_capability_exception($context, $capability, 'nopermissions', '');
+        }
+
         $params = array('userids' => $userids, 'userid' => $userid);
         $params = self::validate_parameters(self::create_contacts_parameters(), $params);
 
@@ -276,13 +289,26 @@ class core_message_external extends external_api {
      * @since Moodle 2.5
      */
     public static function delete_contacts($userids, $userid = 0) {
-        global $CFG;
+        global $CFG, $USER;
 
         // Check if messaging is enabled.
         if (empty($CFG->messaging)) {
             throw new moodle_exception('disabled', 'message');
         }
 
+        if (empty($userid)) {
+            $userid = $USER->id;
+        }
+
+        // Validate context.
+        $context = context_system::instance();
+        self::validate_context($context);
+
+        $capability = 'moodle/site:manageallmessaging';
+        if (($USER->id != $userid) && !has_capability($capability, $context)) {
+            throw new required_capability_exception($context, $capability, 'nopermissions', '');
+        }
+
         $params = array('userids' => $userids, 'userid' => $userid);
         $params = self::validate_parameters(self::delete_contacts_parameters(), $params);
 
@@ -331,13 +357,26 @@ class core_message_external extends external_api {
      * @since Moodle 2.5
      */
     public static function block_contacts($userids, $userid = 0) {
-        global $CFG;
+        global $CFG, $USER;
 
         // Check if messaging is enabled.
         if (empty($CFG->messaging)) {
             throw new moodle_exception('disabled', 'message');
         }
 
+        if (empty($userid)) {
+            $userid = $USER->id;
+        }
+
+        // Validate context.
+        $context = context_system::instance();
+        self::validate_context($context);
+
+        $capability = 'moodle/site:manageallmessaging';
+        if (($USER->id != $userid) && !has_capability($capability, $context)) {
+            throw new required_capability_exception($context, $capability, 'nopermissions', '');
+        }
+
         $params = array('userids' => $userids, 'userid' => $userid);
         $params = self::validate_parameters(self::block_contacts_parameters(), $params);
 
@@ -393,13 +432,26 @@ class core_message_external extends external_api {
      * @since Moodle 2.5
      */
     public static function unblock_contacts($userids, $userid = 0) {
-        global $CFG;
+        global $CFG, $USER;
 
         // Check if messaging is enabled.
         if (empty($CFG->messaging)) {
             throw new moodle_exception('disabled', 'message');
         }
 
+        if (empty($userid)) {
+            $userid = $USER->id;
+        }
+
+        // Validate context.
+        $context = context_system::instance();
+        self::validate_context($context);
+
+        $capability = 'moodle/site:manageallmessaging';
+        if (($USER->id != $userid) && !has_capability($capability, $context)) {
+            throw new required_capability_exception($context, $capability, 'nopermissions', '');
+        }
+
         $params = array('userids' => $userids, 'userid' => $userid);
         $params = self::validate_parameters(self::unblock_contacts_parameters(), $params);
 
@@ -1590,7 +1642,12 @@ class core_message_external extends external_api {
      * @return external_description
      */
     public static function get_unread_conversations_count($useridto) {
-        global $USER;
+        global $USER, $CFG;
+
+        // Check if messaging is enabled.
+        if (empty($CFG->messaging)) {
+            throw new moodle_exception('disabled', 'message');
+        }
 
         $params = self::validate_parameters(
             self::get_unread_conversations_count_parameters(),
@@ -1656,6 +1713,11 @@ class core_message_external extends external_api {
     public static function get_blocked_users($userid) {
         global $CFG, $USER, $PAGE;
 
+        // Check if messaging is enabled.
+        if (empty($CFG->messaging)) {
+            throw new moodle_exception('disabled', 'message');
+        }
+
         // Warnings array, it can be empty at the end but is mandatory.
         $warnings = array();
 
@@ -1679,8 +1741,9 @@ class core_message_external extends external_api {
         core_user::require_active_user($user);
 
         // Check if we have permissions for retrieve the information.
-        if ($userid != $USER->id and !has_capability('moodle/site:readallmessages', $context)) {
-            throw new moodle_exception('accessdenied', 'admin');
+        $capability = 'moodle/site:manageallmessaging';
+        if (($USER->id != $userid) && !has_capability($capability, $context)) {
+            throw new required_capability_exception($context, $capability, 'nopermissions', '');
         }
 
         // Now, we can get safely all the blocked users.
@@ -1843,7 +1906,12 @@ class core_message_external extends external_api {
      * @return external_description
      */
     public static function mark_all_messages_as_read($useridto, $useridfrom) {
-        global $USER;
+        global $USER, $CFG;
+
+        // Check if messaging is enabled.
+        if (empty($CFG->messaging)) {
+            throw new moodle_exception('disabled', 'message');
+        }
 
         $params = self::validate_parameters(
             self::mark_all_messages_as_read_parameters(),
@@ -2092,7 +2160,12 @@ class core_message_external extends external_api {
      * @since 3.2
      */
     public static function message_processor_config_form($userid, $name, $formvalues) {
-        global $USER;
+        global $USER, $CFG;
+
+        // Check if messaging is enabled.
+        if (empty($CFG->messaging)) {
+            throw new moodle_exception('disabled', 'message');
+        }
 
         $params = self::validate_parameters(
             self::message_processor_config_form_parameters(),
@@ -2162,7 +2235,12 @@ class core_message_external extends external_api {
      * @since 3.2
      */
     public static function get_message_processor($userid = 0, $name) {
-        global $USER, $PAGE;
+        global $USER, $PAGE, $CFG;
+
+        // Check if messaging is enabled.
+        if (empty($CFG->messaging)) {
+            throw new moodle_exception('disabled', 'message');
+        }
 
         $params = self::validate_parameters(
             self::get_message_processor_parameters(),
@@ -2226,7 +2304,12 @@ class core_message_external extends external_api {
      * @since 3.2
      */
     public static function get_user_notification_preferences($userid = 0) {
-        global $USER, $PAGE;
+        global $USER, $PAGE, $CFG;
+
+        // Check if messaging is enabled.
+        if (empty($CFG->messaging)) {
+            throw new moodle_exception('disabled', 'message');
+        }
 
         $params = self::validate_parameters(
             self::get_user_notification_preferences_parameters(),
index 1cf3fc6..aeac026 100644 (file)
         <td class="align-bottom">
             <div class="container-fluid">
                 <div class="row-fluid">
-                    <div class="span6">
+                    <div class="span6 col-xs-6">
                         {{#str}} loggedin, message {{/str}}
                         {{#onlinehelphtml}}{{{.}}}{{/onlinehelphtml}}
                     </div>
-                    <div class="span6">
+                    <div class="span6 col-xs-6">
                         {{#str}} loggedoff, message {{/str}}
                         {{#offlinehelphtml}}{{{.}}}{{/offlinehelphtml}}
                     </div>
index 0e35d4a..43c38ef 100644 (file)
@@ -69,7 +69,7 @@
             <form>
                 <div class="container-fluid">
                     <div class="row-fluid">
-                        <div class="span6">
+                        <div class="span6 col-xs-6">
                             {{#loggedin}}
                                 {{< core/hover_tooltip }}
                                     {{$anchor}}
@@ -94,7 +94,7 @@
                                 {{/ core/hover_tooltip }}
                             {{/loggedin}}
                         </div>
-                        <div class="span6">
+                        <div class="span6 col-xs-6">
                             {{#loggedoff}}
                                 {{< core/hover_tooltip }}
                                     {{$anchor}}
index c220e71..59f5295 100644 (file)
         <td class="align-bottom">
             <div class="container-fluid">
                 <div class="row-fluid">
-                    <div class="span6">
+                    <div class="span6 col-xs-6">
                         {{#str}} loggedin, message {{/str}}
                         {{#onlinehelphtml}}{{{.}}}{{/onlinehelphtml}}
                     </div>
-                    <div class="span6">
+                    <div class="span6 col-xs-6">
                         {{#str}} loggedoff, message {{/str}}
                         {{#offlinehelphtml}}{{{.}}}{{/offlinehelphtml}}
                     </div>
index acc39f8..0f10767 100644 (file)
@@ -67,7 +67,7 @@
                 <form>
                     <div class="container-fluid">
                         <div class="row-fluid">
-                            <div class="span6">
+                            <div class="span6 col-xs-6">
                                 {{#loggedin}}
                                     {{< core/hover_tooltip }}
                                         {{$anchor}}
@@ -92,7 +92,7 @@
                                     {{/ core/hover_tooltip }}
                                 {{/loggedin}}
                             </div>
-                            <div class="span6">
+                            <div class="span6 col-xs-6">
                                 {{#loggedoff}}
                                     {{< core/hover_tooltip }}
                                         {{$anchor}}
index d983273..48c7826 100644 (file)
@@ -174,6 +174,8 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
      * Tests searching users.
      */
     public function test_search_users() {
+        global $DB;
+
         // Create some users.
         $user1 = new stdClass();
         $user1->firstname = 'User';
@@ -224,11 +226,32 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
         $course3->shortname = 'Three search';
         $course3 = $this->getDataGenerator()->create_course($course3);
 
+        $course4 = new stdClass();
+        $course4->fullname = 'Course Four';
+        $course4->shortname = 'CF100';
+        $course4 = $this->getDataGenerator()->create_course($course4);
+
+        $course5 = new stdClass();
+        $course5->fullname = 'Course';
+        $course5->shortname = 'Five search';
+        $course5 = $this->getDataGenerator()->create_course($course5);
+
+        $role = $DB->get_record('role', ['shortname' => 'student']);
+        $this->getDataGenerator()->enrol_user($user1->id, $course1->id, $role->id);
+        $this->getDataGenerator()->enrol_user($user1->id, $course2->id, $role->id);
+        $this->getDataGenerator()->enrol_user($user1->id, $course3->id, $role->id);
+        $this->getDataGenerator()->enrol_user($user1->id, $course5->id, $role->id);
+
         // Add some users as contacts.
         message_add_contact($user2->id, 0, $user1->id);
         message_add_contact($user3->id, 0, $user1->id);
         message_add_contact($user4->id, 0, $user1->id);
 
+        // Remove the viewparticipants capability from one of the courses.
+        $course5context = context_course::instance($course5->id);
+        assign_capability('moodle/course:viewparticipants', CAP_PROHIBIT, $role->id, $course5context->id);
+        $course5context->mark_dirty();
+
         // Perform a search.
         list($contacts, $courses, $noncontacts) = \core_message\api::search_users($user1->id, 'search');
 
index 8c371e0..2d0678a 100644 (file)
@@ -161,6 +161,11 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
         $return = array_pop($return);
         $this->assertEquals($return['warningcode'], 'contactnotcreated');
         $this->assertEquals($return['itemid'], 99999);
+
+        // Try to add a contact to another user, should throw an exception.
+        // All assertions must be added before this point.
+        $this->expectException('required_capability_exception');
+        core_message_external::create_contacts(array($user2->id), $user3->id);
     }
 
     /**
@@ -198,6 +203,11 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
         // Removing mixed valid and invalid data.
         $return = core_message_external::delete_contacts(array($user6->id, 99999));
         $this->assertNull($return);
+
+        // Try to delete a contact of another user contact list, should throw an exception.
+        // All assertions must be added before this point.
+        $this->expectException('required_capability_exception');
+        core_message_external::delete_contacts(array($user2->id), $user3->id);
     }
 
     /**
@@ -244,6 +254,11 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
         $return = array_pop($return);
         $this->assertEquals($return['warningcode'], 'contactnotblocked');
         $this->assertEquals($return['itemid'], 99999);
+
+        // Try to block a contact of another user contact list, should throw an exception.
+        // All assertions must be added before this point.
+        $this->expectException('required_capability_exception');
+        core_message_external::block_contacts(array($user2->id), $user3->id);
     }
 
     /**
@@ -282,6 +297,10 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
         $return = core_message_external::unblock_contacts(array($user6->id, 99999));
         $this->assertNull($return);
 
+        // Try to unblock a contact of another user contact list, should throw an exception.
+        // All assertions must be added before this point.
+        $this->expectException('required_capability_exception');
+        core_message_external::unblock_contacts(array($user2->id), $user3->id);
     }
 
     /**
@@ -1172,6 +1191,15 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
         $course3->shortname = 'Three search';
         $course3 = $this->getDataGenerator()->create_course($course3);
 
+        $course4 = new stdClass();
+        $course4->fullname = 'Course Four';
+        $course4->shortname = 'CF100';
+        $course4 = $this->getDataGenerator()->create_course($course4);
+
+        $this->getDataGenerator()->enrol_user($user1->id, $course1->id, 'student');
+        $this->getDataGenerator()->enrol_user($user1->id, $course2->id, 'student');
+        $this->getDataGenerator()->enrol_user($user1->id, $course3->id, 'student');
+
         // Add some users as contacts.
         message_add_contact($user2->id, 0, $user1->id);
         message_add_contact($user3->id, 0, $user1->id);
@@ -1283,9 +1311,7 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
         $this->assertEquals($user2->id, $contacts[1]['userid']);
 
         // Check that we retrieved the correct courses.
-        $this->assertCount(2, $courses);
-        $this->assertEquals($course3->id, $courses[0]['id']);
-        $this->assertEquals($course1->id, $courses[1]['id']);
+        $this->assertCount(0, $courses);
 
         // Check that we retrieved the correct non-contacts.
         $this->assertCount(1, $noncontacts);
index b815f75..b190040 100644 (file)
@@ -1506,7 +1506,7 @@ class mod_assign_external extends external_api {
      * @param int $userid The id of the user the submission belongs to.
      * @param string $jsonformdata The data from the form, encoded as a json array.
      * @return array of warnings to indicate any errors.
-     * @since Moodle 2.6
+     * @since Moodle 3.1
      */
     public static function submit_grading_form($assignmentid, $userid, $jsonformdata) {
         global $CFG, $USER;
@@ -1537,6 +1537,12 @@ class mod_assign_external extends external_api {
             'gradingpanel' => true
         );
 
+        if (WS_SERVER) {
+            // Assume form submission if coming from WS.
+            $USER->ignoresesskey = true;
+            $data['_qf__mod_assign_grade_form_'.$params['userid']] = 1;
+        }
+
         $customdata = (object) $data;
         $formparams = array($assignment, $customdata, $options);
 
@@ -2370,6 +2376,9 @@ class mod_assign_external extends external_api {
                                                                             $lastattempt->submissiongroupmemberswhoneedtosubmit);
             }
 
+            // Can edit its own submission?
+            $lastattempt->caneditowner = $assign->submissions_open($user->id) && $assign->is_any_submission_plugin_enabled();
+
             $result['lastattempt'] = $lastattempt;
         }
 
@@ -2464,6 +2473,7 @@ class mod_assign_external extends external_api {
                         'locked' => new external_value(PARAM_BOOL, 'Whether new submissions are locked.'),
                         'graded' => new external_value(PARAM_BOOL, 'Whether the submission is graded.'),
                         'canedit' => new external_value(PARAM_BOOL, 'Whether the user can edit the current submission.'),
+                        'caneditowner' => new external_value(PARAM_BOOL, 'Whether the owner of the submission can edit it.'),
                         'cansubmit' => new external_value(PARAM_BOOL, 'Whether the user can submit.'),
                         'extensionduedate' => new external_value(PARAM_INT, 'Extension due date.'),
                         'blindmarking' => new external_value(PARAM_BOOL, 'Whether blind marking is enabled.'),
index 700b4a3..09cea5f 100644 (file)
@@ -137,8 +137,8 @@ $string['deleteallsubmissions'] = 'Delete all submissions';
 $string['description'] = 'Description';
 $string['downloadall'] = 'Download all submissions';
 $string['download all submissions'] = 'Download all submissions in a zip file.';
-$string['downloadasfolders'] = 'Download as separate folders';
-$string['downloadasfolders_help'] = 'When enabled downloaded files will be placed in separate folders and files will not be renamed.';
+$string['downloadasfolders'] = 'Download submissions in folders';
+$string['downloadasfolders_help'] = 'If the assignment submission is more than a single file, then submissions may be downloaded in folders. Each submission is put in a separate folder, with the folder structure kept for any subfolders, and files are not renamed.';
 $string['downloadselectedsubmissions'] = 'Download selected submissions';
 $string['duedate'] = 'Due date';
 $string['duedatecolon'] = 'Due date: {$a}';
index cc7df13..168cf83 100644 (file)
@@ -106,7 +106,7 @@ $string['configtypes'] = 'Enable LTI applications';
 $string['configured'] = 'Configured';
 $string['confirmtoolactivation'] = 'Are you sure you would like to activate this tool?';
 $string['contentitem'] = 'Content-Item Message';
-$string['contentitem_help'] = 'If ticked, the option \'Configure tool from link\' will be available when adding an external tool.';
+$string['contentitem_help'] = 'If ticked, the option \'Select content\' will be available when adding an external tool.';
 $string['course_tool_types'] = 'Course tools';
 $string['courseactivitiesorresources'] = 'Course activities or resources';
 $string['courseid'] = 'Course ID number';
index 8c79287..2ae58be 100644 (file)
 
 defined('MOODLE_INTERNAL') || die();
 
-$string['allowofflineattempts'] = 'Allow quiz to be attempted offline in the mobile app';
-$string['allowofflineattempts_help'] = 'If checked, the user will be able to download the quiz to attempt it offline using the Mobile app. If the user download a quiz for offline, a new attempt will be created. This attempt will be empty until the user synchronize the results of the attempt in the Mobile app.';
-$string['confirmdatasaved'] = 'I confirm that I don’t have unsaved work on my mobile devices before continuing this attempt.';
+$string['allowofflineattempts'] = 'Allow quiz to be attempted offline using the mobile app';
+$string['allowofflineattempts_help'] = 'If enabled, a mobile app user can download the quiz and attempt it offline.
+
+Note: It is not possible for a quiz to be attempted offline if it has a time limit, or requires a network address, or uses any question behaviour other than deferred feedback (with or without CBM).';
+$string['confirmdatasaved'] = 'I confirm that I do not have any unsaved work on a mobile device.';
 $string['mobileapp'] = 'Mobile app';
-$string['offlineattemptserror'] = 'Offline quizzes are not compatible with quizzes using timers, access restriction by password or subnet and quizzes using behaviours different than deferred feedback without or with CBM';
-$string['offlinedatamessage'] = 'You have worked on this attempt in a mobile device, and that data was last saved to this site {$a} ago.';
-$string['pleaseconfirm'] = 'Please, confirm that you don\'t have unsaved work on your devices';
+$string['offlineattemptserror'] = 'It is not possible for a quiz to be attempted offline if it has a time limit, or requires a network address, or uses any question behaviour other than deferred feedback (with or without CBM).';
+$string['offlinedatamessage'] = 'You have worked on this attempt using a mobile device. Data was last saved to this site {$a} ago.';
+$string['pleaseconfirm'] = 'Please check and confirm that you do not have any unsaved work.';
 $string['pluginname'] = 'Offline attempts access rule';
 
index 7f25273..d360884 100644 (file)
@@ -704,7 +704,7 @@ $string['readytosend'] = 'You are about to send your whole quiz to be graded.  A
 $string['reattemptquiz'] = 'Re-attempt quiz';
 $string['recentlyaddedquestion'] = 'Recently added question!';
 $string['recurse'] = 'Include questions from subcategories too';
-$string['redoquestion'] = 'Redo question';
+$string['redoquestion'] = 'Try another question like this one';
 $string['redoesofthisquestion'] = 'Other questions attempted here: {$a}';
 $string['regrade'] = 'Regrade all attempts';
 $string['regradecomplete'] = 'All attempts have been regraded';
index 2760fa1..5fcda3c 100644 (file)
@@ -39,7 +39,7 @@ Feature: Allow students to redo questions in a practice quiz, without starting a
     And I press "Attempt quiz now"
     And I click on "False" "radio" in the "First question" "question"
     And I click on "Check" "button" in the "First question" "question"
-    And I press "Redo question"
+    And I press "Try another question like this one"
     Then the state of "First question" question is shown as "Not complete"
     And I should see "Marked out of 2.00" in the "First question" "question"
 
@@ -55,7 +55,7 @@ Feature: Allow students to redo questions in a practice quiz, without starting a
     And I follow "Quiz 1"
     And I follow "Attempts: 1"
     And I follow "Review attempt"
-    Then the "Redo question" "button" should be disabled
+    Then the "Try another question like this one" "button" should be disabled
 
   @javascript
   Scenario: The redo question buttons are no longer visible after the attempt is submitted.
@@ -66,7 +66,7 @@ Feature: Allow students to redo questions in a practice quiz, without starting a
     And I press "Finish attempt ..."
     And I press "Submit all and finish"
     And I click on "Submit all and finish" "button" in the "Confirmation" "dialogue"
-    Then "Redo question" "button" should not exist
+    Then "Try another question like this one" "button" should not exist
 
   @javascript @_switch_window
   Scenario: Teachers reviewing can see all the qestions attempted in a slot
@@ -74,7 +74,7 @@ Feature: Allow students to redo questions in a practice quiz, without starting a
     And I press "Attempt quiz now"
     And I click on "False" "radio" in the "First question" "question"
     And I click on "Check" "button" in the "First question" "question"
-    And I press "Redo question"
+    And I press "Try another question like this one"
     And I press "Finish attempt ..."
     And I press "Submit all and finish"
     And I click on "Submit all and finish" "button" in the "Confirmation" "dialogue"
@@ -105,6 +105,6 @@ Feature: Allow students to redo questions in a practice quiz, without starting a
     And I click on "False" "radio" in the "First question" "question"
     And I click on "Check" "button" in the "First question" "question"
     And I click on "True" "radio" in the "Second question" "question"
-    And I press "Redo question"
+    And I press "Try another question like this one"
     And I click on "Check" "button" in the "Second question" "question"
     Then the state of "Second question" question is shown as "Correct"
index b112371..f56e297 100644 (file)
@@ -33,8 +33,8 @@ $string['answerstoleranceparam'] = 'Answers tolerance parameters';
 $string['answerwithtolerance'] = '{$a->answer} (±{$a->tolerance} {$a->tolerancetype})';
 $string['anyvalue'] = 'Any value';
 $string['atleastoneanswer'] = 'You need to provide at least one answer.';
-$string['atleastonerealdataset']='There should be at least one real dataset in question text';
-$string['atleastonewildcard']='There should be at least one wild card in answer formula or question text';
+$string['atleastonerealdataset'] = 'There should be at least one real dataset in question text';
+$string['atleastonewildcard'] = 'There should be at least one wild card in answer formula or question text';
 $string['calcdistribution'] = 'Distribution';
 $string['calclength'] = 'Decimal places';
 $string['calcmax'] = 'Maximum';
@@ -45,8 +45,8 @@ $string['correctanswerformula'] = 'Correct answer formula';
 $string['correctanswershows'] = 'Correct answer shows';
 $string['correctanswershowsformat'] = 'Format';
 $string['correctfeedback'] = 'For any correct response';
-$string['dataitemdefined']='with {$a} numerical values already defined is available';
-$string['datasetrole']= ' The wild cards <strong>{x..}</strong> will be substituted by a numerical value from their dataset';
+$string['dataitemdefined'] = 'with {$a} numerical values already defined is available';
+$string['datasetrole'] = ' The wild cards <strong>{x..}</strong> will be substituted by a numerical value from their dataset';
 $string['decimals'] = 'with {$a}';
 $string['deleteitem'] = 'Delete item';
 $string['deletelastitem'] = 'Delete last item';
@@ -72,7 +72,7 @@ $string['illegalformulasyntax'] = 'Illegal formula syntax starting with \'{$a}\'
 $string['incorrectfeedback'] = 'For any incorrect response';
 $string['item(s)'] = 'item(s)';
 $string['itemno'] = 'Item {$a}';
-$string['itemscount']='Items<br />Count';
+$string['itemscount'] = 'Items<br />Count';
 $string['itemtoadd'] = 'Item to add';
 $string['keptcategory1'] = 'will use the same existing shared dataset as before';
 $string['keptcategory2'] = 'a file from the same category reusable set of files as before';
@@ -118,18 +118,18 @@ $string['pluginnamesummary'] = 'Calculated questions are like numerical question
 $string['possiblehdr'] = 'Possible wild cards present only in the question text';
 $string['questiondatasets'] = 'Question datasets';
 $string['questiondatasets_help'] = 'Question datasets of wild cards that will be used in each individual question';
-$string['questionstoredname'] ='Question stored name';
+$string['questionstoredname'] = 'Question stored name';
 $string['replacewithrandom'] = 'Replace with a random value';
 $string['reuseifpossible'] = 'reuse previous value if available';
-$string['sharedwildcard']='Shared wild card {<strong>{$a}</strong>}';
-$string['sharedwildcardname']='Shared wild card ';
-$string['sharedwildcards']='Shared wild cards';
+$string['sharedwildcard'] = 'Shared wild card {<strong>{$a}</strong>}';
+$string['sharedwildcardname'] = 'Shared wild card ';
+$string['sharedwildcards'] = 'Shared wild cards';
 $string['significantfigures'] = 'with {$a}';
 $string['significantfiguresformat'] = 'significant figures';
-$string['synchronize']='Synchronize the data from shared datasets with other questions in a quiz';
-$string['synchronizeno']='Do not synchronize';
-$string['synchronizeyes']='Synchronize';
-$string['synchronizeyesdisplay']='Synchronize and display the shared datasets name as prefix of the question name';
+$string['synchronize'] = 'Synchronise the data from shared datasets with other questions in a quiz';
+$string['synchronizeno'] = 'Do not synchronise';
+$string['synchronizeyes'] = 'Synchronise';
+$string['synchronizeyesdisplay'] = 'Synchronise and display the shared datasets name as prefix of the question name';
 $string['tolerance'] = 'Tolerance &plusmn;';
 $string['tolerancetype'] = 'Type';
 $string['trueanswerinsidelimits'] = 'Correct answer : {$a->correct} inside limits of true value {$a->true}';
index 44c39f0..c8e08c1 100644 (file)
@@ -27,7 +27,7 @@ defined('MOODLE_INTERNAL') || die();
 require_once(__DIR__ . '/lib.php');
 
 $THEME->name = 'boost';
-$THEME->scssfile = theme_boost_get_scss_file($THEME);
+$THEME->scssfile = 'preset';
 $THEME->sheets = [];
 $THEME->editor_sheets = [];
 
index 99dc7cd..3bae9c0 100644 (file)
@@ -27,20 +27,17 @@ defined('MOODLE_INTERNAL') || die();
 $string['advancedsettings'] = 'Advanced settings';
 $string['brandcolor'] = 'Brand colour';
 $string['brandcolor_desc'] = 'The accent colour.';
-$string['choosereadme'] = 'Boost is a modern highly customizable theme. This theme is intended to be used directly, or used as a parent theme when creating new themes utilising Boostrap 4.';
+$string['choosereadme'] = 'Boost is a modern highly-customisable theme. This theme is intended to be used directly, or as a parent theme when creating new themes utilising Bootstrap 4.';
 $string['currentinparentheses'] = '(current)';
 $string['configtitle'] = 'Boost';
 $string['generalsettings'] = 'General settings';
 $string['pluginname'] = 'Boost';
+$string['presetfiles'] = 'Additional theme preset files';
+$string['presetfiles_desc'] = 'Preset files can be used to dramatically alter the appearance of the theme. See https://docs.moodle.org/dev/Boost_Presets for information on creating and sharing your own preset files.';
 $string['preset'] = 'Theme preset';
 $string['preset_desc'] = 'Pick a preset to broadly change the look of the theme.';
-$string['presetdefault'] = 'Default';
-$string['presetflatly'] = 'Flatly';
-$string['presetpaper'] = 'Paper';
-$string['presetplain'] = 'Plain';
-$string['presetreadable'] = 'Readable';
 $string['rawscss'] = 'Raw SCSS';
-$string['rawscss_desc'] = 'Use this field to provide SCSS code which will be injected at the end of the stylesheet.';
+$string['rawscss_desc'] = 'Use this field to provide SCSS code which will be injected at the end of the style sheet.';
 $string['rawscsspre'] = 'Raw initial SCSS';
 $string['rawscsspre_desc'] = '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.';
 $string['region-side-pre'] = 'Right';
index 6f18143..cc12f19 100644 (file)
@@ -35,17 +35,6 @@ function theme_boost_css_tree_post_processor($tree, $theme) {
     $prefixer->prefix();
 }
 
-/**
- * Get the SCSS file to include.
- *
- * @param theme_config $theme The theme config object.
- * @return string The name of the file without 'scss'.
- */
-function theme_boost_get_scss_file($theme) {
-    $preset = !empty($theme->settings->preset) ? $theme->settings->preset : 'default';
-    return 'preset-' . $preset;
-}
-
 /**
  * Inject additional SCSS.
  *
@@ -63,6 +52,8 @@ function theme_boost_get_extra_scss($theme) {
  * @return array
  */
 function theme_boost_get_pre_scss($theme) {
+    global $CFG;
+
     $scss = '';
     $configurable = [
         // Config key => [variableName, ...].
@@ -85,5 +76,21 @@ function theme_boost_get_pre_scss($theme) {
         $scss .= $theme->settings->scsspre;
     }
 
+    // Now append the preset.
+    $filename = $theme->settings->preset;
+    $fs = get_file_storage();
+
+    $context = context_system::instance();
+    if ($filename == 'default.scss') {
+        $scss .= file_get_contents($CFG->dirroot . '/theme/boost/scss/preset/default.scss');
+    } else if ($filename == 'plain.scss') {
+        $scss .= file_get_contents($CFG->dirroot . '/theme/boost/scss/preset/plain.scss');
+    } else if ($filename && ($presetfile = $fs->get_file($context->id, 'theme_boost', 'preset', 0, '/', $filename))) {
+        $scss .= $presetfile->get_content();
+    } else {
+        // Safety fallback - maybe new installs etc.
+        $scss .= file_get_contents($CFG->dirroot . '/theme/boost/scss/preset/default.scss');
+    }
+
     return $scss;
 }
index 7ad3b0d..99be7fc 100644 (file)
Binary files a/theme/boost/pix/screenshot.jpg and b/theme/boost/pix/screenshot.jpg differ
index 977acd5..ae43bf4 100644 (file)
 }
 
 .maintenancewarning {
-    padding: 3px 1em;
-    text-align: center;
     position: fixed;
     bottom: 0;
     right: 0;
index 21ffa00..3dd3ee7 100644 (file)
@@ -33,6 +33,19 @@ $blocks-column-width: 250px !default;
 
 $blocks-plus-gutter: $blocks-column-width + $grid-gutter-width;
 
+/* We put an absolutely positioned div in a relatively positioned div so it takes up no space */
+#region-main-settings-menu {
+    position: relative;
+    float: left;
+    width: 100%;
+}
+#region-main-settings-menu > div {
+    position: absolute;
+    right: 0;
+    z-index: 100;
+    margin: 1rem;
+}
+#region-main-settings-menu.has-blocks,
 #region-main.has-blocks {
     display: inline-block;
     width: calc(100% - #{$blocks-plus-gutter});
index 5dc02c1..fdbcb4b 100644 (file)
@@ -15,7 +15,7 @@
 }
 
 .context-header-settings-menu .dropdown-toggle > .icon,
-.region-main-settings-menu .dropdown-toggle > .icon {
+#region-main-settings-menu .dropdown-toggle > .icon {
     height: 24px;
     width: auto;
 }
index 8f5c3ad..1d490ad 100644 (file)
@@ -18,6 +18,7 @@ li.activity.label,
     display: block;
     font-size: inherit;
     line-height: inherit;
+    text-align: inherit;
 }
 
 .file-picker td.label {
diff --git a/theme/boost/scss/preset-flatly.scss b/theme/boost/scss/preset-flatly.scss
deleted file mode 100644 (file)
index 418c0b9..0000000
+++ /dev/null
@@ -1,1266 +0,0 @@
-//
-// The MIT License (MIT)
-//
-// Copyright (c) 2013 Thomas Park
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-$bootstrap-sass-asset-helper: false !default;
-// Flatly 3.3.7
-// Variables
-// --------------------------------------------------
-
-
-//== Colors
-//
-//## Gray and brand colors for use across Bootstrap.
-
-$gray-base:              #000 !default;
-$gray-darker:            lighten($gray-base, 13.5%) !default; // #222
-$gray-dark:              #7b8a8b !default;   // #333
-$gray:                   #95a5a6 !default; // #555
-$gray-light:             #b4bcc2 !default;   // #999
-$gray-lighter:           #ecf0f1 !default; // #eee
-
-$gray-lightest:          lighten($gray-lighter, 13.5%);
-
-$brand-primary:         #2C3E50 !default;
-$brand-success:         #18BC9C !default;
-$brand-info:            #3498DB !default;
-$brand-warning:         #F39C12 !default;
-$brand-danger:          #E74C3C !default;
-
-
-//== Scaffolding
-//
-//## Settings for some of the most global styles.
-
-//** Background color for `<body>`.
-$body-bg:               #fff !default;
-//** Global text color on `<body>`.
-$text-color:            $brand-primary !default;
-
-$body-color: $text-color;
-
-//** Global textual link color.
-$link-color:            $brand-success !default;
-//** Link hover color set via `darken()` function.
-$link-hover-color:      $link-color !default;
-//** Link hover decoration.
-$link-hover-decoration: underline !default;
-
-
-//== Typography
-//
-//## Font, line-height, and color for body text, headings, and more.
-
-$font-family-sans-serif:  "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif !default;
-$font-family-serif:       Georgia, "Times New Roman", Times, serif !default;
-//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
-$font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace !default;
-$font-family-base:        $font-family-sans-serif !default;
-
-$font-size-base:          15px !default;
-$font-size-root: $font-size-base;
-
-$font-size-lg:         ceil(($font-size-base * 1.25)) !default; // ~18px
-$font-size-sm:         ceil(($font-size-base * 0.85)) !default; // ~12px
-
-$font-size-h1:            floor(($font-size-base * 2.6)) !default; // ~36px
-$font-size-h2:            floor(($font-size-base * 2.15)) !default; // ~30px
-$font-size-h3:            ceil(($font-size-base * 1.7)) !default; // ~24px
-$font-size-h4:            ceil(($font-size-base * 1.25)) !default; // ~18px
-$font-size-h5:            $font-size-base !default;
-$font-size-h6:            ceil(($font-size-base * 0.85)) !default; // ~12px
-
-//** Unit-less `line-height` for use in components like buttons.
-$line-height-base:        1.428571429 !default; // 20/14
-//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
-$line-height-computed:    floor(($font-size-base * $line-height-base)) !default; // ~20px
-
-//** By default, this inherits from the `<body>`.
-$headings-font-family:    $font-family-base !default;
-$headings-font-weight:    400 !default;
-$headings-line-height:    1.1 !default;
-$headings-color:          inherit !default;
-
-
-//== Iconography
-//
-//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
-
-//** Load fonts from this directory.
-$icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/") !default;
-//** File name for all font files.
-$icon-font-name:          "glyphicons-halflings-regular" !default;
-//** Element ID within SVG icon file.
-$icon-font-svg-id:        "glyphicons_halflingsregular" !default;
-
-
-//== Components
-//
-//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
-
-$padding-base-y:     10px !default;
-$padding-base-x:   15px !default;
-
-$padding-lg-y:    18px !default;
-$padding-lg-x:  27px !default;
-
-$padding-sm-y:    6px !default;
-$padding-sm-x:  9px !default;
-
-$padding-xs-y:       1px !default;
-$padding-xs-x:     5px !default;
-
-$line-height-lg:         1.3333333 !default; // extra decimals for Win 8.1 Chrome
-$line-height-sm:         1.5 !default;
-
-$border-radius:        4px !default;
-$border-radius-lg:       6px !default;
-$border-radius-sm:       3px !default;
-
-//** Global color for active items (e.g., navs or dropdowns).
-$component-active-color:    #fff !default;
-//** Global background color for active items (e.g., navs or dropdowns).
-$component-active-bg:       $brand-primary !default;
-
-//** Width of the `border` for generating carets that indicate dropdowns.
-$caret-width-base:          4px !default;
-//** Carets increase slightly in size for lgr components.
-$caret-width-lg:         5px !default;
-
-
-//== Tables
-//
-//## Customizes the `.table` component with basic values, each used across all table variations.
-
-//** Padding for `<th>`s and `<td>`s.
-$table-cell-padding:            8px !default;
-//** Padding for cells in `.table-condensed`.
-$table-sm-cell-padding:  5px !default;
-
-//** Default background color used for all tables.
-$table-bg:                      transparent !default;
-//** Background color used for `.table-striped`.
-$table-bg-accent:               #f9f9f9 !default;
-//** Background color used for `.table-hover`.
-$table-bg-hover:                $gray-lighter !default;
-$table-bg-active:               $table-bg-hover !default;
-
-//** Border color for table and cell borders.
-$table-border-color:            $gray-lighter !default;
-
-
-//== Buttons
-//
-//## For each of Bootstrap's buttons, define text, background and border color.
-
-$btn-font-weight:                normal !default;
-
-$btn-default-color:              #fff !default;
-$btn-default-bg:                 $gray !default;
-$btn-default-border:             $btn-default-bg !default;
-
-$btn-secondary-color: $btn-default-color;
-$btn-secondary-bg: $btn-default-bg;
-$btn-secondary-border: $btn-default-border;
-
-
-
-$btn-primary-color:              $btn-default-color !default;
-$btn-primary-bg:                 $brand-primary !default;
-$btn-primary-border:             $btn-primary-bg !default;
-
-$btn-success-color:              $btn-default-color !default;
-$btn-success-bg:                 $brand-success !default;
-$btn-success-border:             $btn-success-bg !default;
-
-$btn-info-color:                 $btn-default-color !default;
-$btn-info-bg:                    $brand-info !default;
-$btn-info-border:                $btn-info-bg !default;
-
-$btn-warning-color:              $btn-default-color !default;
-$btn-warning-bg:                 $brand-warning !default;
-$btn-warning-border:             $btn-warning-bg !default;
-
-$btn-danger-color:               $btn-default-color !default;
-$btn-danger-bg:                  $brand-danger !default;
-$btn-danger-border:              $btn-danger-bg !default;
-
-$btn-link-disabled-color:        $gray-light !default;
-
-// Allows for customizing button radius independently from global border radius
-$btn-border-radius:         $border-radius !default;
-$btn-border-radius-lg:        $border-radius-lg !default;
-$btn-border-radius-sm:        $border-radius-sm !default;
-
-
-//== Forms
-//
-//##
-
-//** `<input>` background color
-$input-bg:                       #fff !default;
-//** `<input disabled>` background color
-$input-bg-disabled:              $gray-lighter !default;
-
-//** Text color for `<input>`s
-$input-color:                    $text-color !default;
-//** `<input>` border color
-$input-border:                   #dce4ec !default;
-
-// TODO: Rename `$input-border-radius` to `$input-border-radius` in v4
-//** Default `.form-control` border radius
-// This has no effect on `<select>`s in some browsers, due to the limited stylability of `<select>`s in CSS.
-$input-border-color: $input-border;
-
-$input-border-radius:            $border-radius !default;
-//** Large `.form-control` border radius
-$input-border-radius-lg:      $border-radius-lg !default;
-//** Small `.form-control` border radius
-$input-border-radius-sm:      $border-radius-sm !default;
-
-//** Border color for inputs on focus
-$input-border-focus:             $brand-primary !default;
-
-//** Placeholder text color
-$input-color-placeholder:        #acb6c0 !default;
-
-//** Default `.form-control` height
-$input-height:              ($line-height-computed + ($padding-base-y * 2) + 4) !default;
-//** Large `.form-control` height
-$input-height-lg:             (ceil($font-size-lg * $line-height-lg) + ($padding-lg-y * 2) + 4) !default;
-//** Small `.form-control` height
-$input-height-sm:             (floor($font-size-sm * $line-height-sm) + ($padding-sm-y * 2) + 4) !default;
-
-//** `.form-group` margin
-$form-group-margin-bottom:       15px !default;
-
-$legend-color:                   $text-color !default;
-$legend-border-color:            transparent !default;
-
-//** Background color for textual input addons
-$input-group-addon-bg:           $gray-lighter !default;
-//** Border color for textual input addons
-$input-group-addon-border-color: $input-border !default;
-
-//** Disabled cursor for form controls and buttons.
-$cursor-disabled:                not-allowed !default;
-
-
-//== Dropdowns
-//
-//## Dropdown menu container and contents.
-
-//** Background for the dropdown menu.
-$dropdown-bg:                    #fff !default;
-//** Dropdown menu `border-color`.
-$dropdown-border:                rgba(0,0,0,.15) !default;
-//** Dropdown menu `border-color` **for IE8**.
-$dropdown-fallback-border:       #ccc !default;
-//** Divider color for between dropdown items.
-$dropdown-divider-bg:            #e5e5e5 !default;
-
-//** Dropdown link text color.
-$dropdown-link-color:            $gray-dark !default;
-//** Hover color for dropdown links.
-$dropdown-link-hover-color:      #fff !default;
-//** Hover background for dropdown links.
-$dropdown-link-hover-bg:         $component-active-bg !default;
-
-//** Active dropdown menu item text color.
-$dropdown-link-active-color:     #fff !default;
-//** Active dropdown menu item background color.
-$dropdown-link-active-bg:        $component-active-bg !default;
-
-//** Disabled dropdown menu item background color.
-$dropdown-link-disabled-color:   $gray-light !default;
-
-//** Text color for headers within dropdown menus.
-$dropdown-header-color:          $gray-light !default;
-
-//** Deprecated `$dropdown-caret-color` as of v3.1.0
-$dropdown-caret-color:           #000 !default;
-
-
-//-- Z-index master list
-//
-// Warning: Avoid customizing these values. They're used for a bird's eye view
-// of components dependent on the z-axis and are designed to all work together.
-//
-// Note: These variables are not generated into the Customizer.
-
-$zindex-navbar:            1000 !default;
-$zindex-dropdown:          1000 !default;
-$zindex-popover:           1060 !default;
-$zindex-tooltip:           1070 !default;
-$zindex-navbar-fixed:      1030 !default;
-$zindex-modal-background:  1040 !default;
-$zindex-modal:             1050 !default;
-
-
-//== Media queries breakpoints
-//
-//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
-
-// Extra sm screen / phone
-//** Deprecated `$screen-xs` as of v3.0.1
-$screen-xs:                  480px !default;
-//** Deprecated `$screen-xs-min` as of v3.2.0
-$screen-xs-min:              $screen-xs !default;
-//** Deprecated `$screen-phone` as of v3.0.1
-$screen-phone:               $screen-xs-min !default;
-
-// Small screen / tablet
-//** Deprecated `$screen-sm` as of v3.0.1
-$screen-sm:                  768px !default;
-$screen-sm-min:              $screen-sm !default;
-//** Deprecated `$screen-tablet` as of v3.0.1
-$screen-tablet:              $screen-sm-min !default;
-
-// Medium screen / desktop
-//** Deprecated `$screen-md` as of v3.0.1
-$screen-md:                  992px !default;
-$screen-md-min:              $screen-md !default;
-//** Deprecated `$screen-desktop` as of v3.0.1
-$screen-desktop:             $screen-md-min !default;
-
-// Large screen / wide desktop
-//** Deprecated `$screen-lg` as of v3.0.1
-$screen-lg:                  1200px !default;
-$screen-lg-min:              $screen-lg !default;
-//** Deprecated `$screen-lg-desktop` as of v3.0.1
-$screen-lg-desktop:          $screen-lg-min !default;
-
-// So media queries don't overlap when required, provide a maximum
-$screen-xs-max:              ($screen-sm-min - 1) !default;
-$screen-sm-max:              ($screen-md-min - 1) !default;
-$screen-md-max:              ($screen-lg-min - 1) !default;
-
-
-//== Grid system
-//
-//## Define your custom responsive grid.
-
-//** Number of columns in the grid.
-$grid-columns:              12 !default;
-//** Padding between columns. Gets divided in half for the left and right.
-$grid-gutter-width:         30px !default;
-// Navbar collapse
-//** Point at which the navbar becomes uncollapsed.
-$grid-float-breakpoint:     $screen-sm-min !default;
-//** Point at which the navbar begins collapsing.
-$grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default;
-
-
-//== Container sizes
-//
-//## Define the maximum width of `.container` for different screen sizes.
-
-// Small screen / tablet
-$container-tablet:             (720px + $grid-gutter-width) !default;
-//** For `$screen-sm-min` and up.
-$container-sm:                 $container-tablet !default;
-
-// Medium screen / desktop
-$container-desktop:            (940px + $grid-gutter-width) !default;
-//** For `$screen-md-min` and up.
-$container-md:                 $container-desktop !default;
-
-// Large screen / wide desktop
-$container-lg-desktop:      (1140px + $grid-gutter-width) !default;
-//** For `$screen-lg-min` and up.
-$container-lg:                 $container-lg-desktop !default;
-
-
-//== Navbar
-//
-//##
-
-// Basics of a navbar
-$navbar-height:                    60px !default;
-$navbar-margin-bottom:             $line-height-computed !default;
-$navbar-border-radius:             $border-radius !default;
-$navbar-padding-x:        floor(($grid-gutter-width / 2)) !default;
-$navbar-padding-y:          (($navbar-height - $line-height-computed) / 2) !default;
-$navbar-collapse-max-height:       340px !default;
-
-$navbar-light-color:             #fff !default;
-$navbar-light-bg:                $brand-primary !default;
-$navbar-light-border:            transparent !default;
-
-// Navbar links
-$navbar-light-link-color:                #fff !default;
-$navbar-light-link-hover-color:          $brand-success !default;
-$navbar-light-link-hover-bg:             transparent !default;
-$navbar-light-link-active-color:         #fff !default;
-$navbar-light-link-active-bg:            darken($navbar-light-bg, 10%) !default;
-$navbar-light-link-disabled-color:       #ccc !default;
-$navbar-light-link-disabled-bg:          transparent !default;
-
-// Navbar brand label
-$navbar-light-brand-color:               $navbar-light-link-color !default;
-$navbar-light-brand-hover-color:         $navbar-light-link-hover-color !default;
-$navbar-light-brand-hover-bg:            transparent !default;
-
-// Navbar toggle
-$navbar-light-toggle-hover-bg:           darken($navbar-light-bg, 10%) !default;
-$navbar-light-toggle-icon-bar-bg:        #fff !default;
-$navbar-light-toggle-border-color:       darken($navbar-light-bg, 10%) !default;
-
-
-//=== Inverted navbar
-// Reset inverted navbar basics
-$navbar-dark-color:                      #fff !default;
-$navbar-dark-bg:                         $brand-success !default;
-$navbar-dark-border:                     transparent !default;
-
-// Inverted navbar links
-$navbar-dark-link-color:                 #fff !default;
-$navbar-dark-link-hover-color:           $brand-primary !default;
-$navbar-dark-link-hover-bg:              transparent !default;
-$navbar-dark-link-active-color:          #fff !default;
-$navbar-dark-link-active-bg:             darken($navbar-dark-bg, 5%) !default;
-$navbar-dark-link-disabled-color:        #ccc !default;
-$navbar-dark-link-disabled-bg:           transparent !default;
-
-// Inverted navbar brand label
-$navbar-dark-brand-color:                $navbar-dark-link-color !default;
-$navbar-dark-brand-hover-color:          $navbar-dark-link-hover-color !default;
-$navbar-dark-brand-hover-bg:             transparent !default;
-
-// Inverted navbar toggle
-$navbar-dark-toggle-hover-bg:            darken($navbar-dark-bg, 10%) !default;
-$navbar-dark-toggle-icon-bar-bg:         #fff !default;
-$navbar-dark-toggle-border-color:        darken($navbar-dark-bg, 10%) !default;
-
-
-//== Navs
-//
-//##
-
-//=== Shared nav styles
-$nav-link-padding:                          10px 15px !default;
-$nav-link-hover-bg:                         $gray-lighter !default;
-
-$nav-disabled-link-color:                   $gray-light !default;
-$nav-disabled-link-hover-color:             $gray-light !default;
-
-//== Tabs
-$nav-tabs-border-color:                     $gray-lighter !default;
-
-$nav-tabs-link-hover-border-color:          $gray-lighter !default;
-
-$nav-tabs-active-link-hover-bg:             $body-bg !default;
-$nav-tabs-active-link-hover-color:          $brand-primary !default;
-$nav-tabs-active-link-hover-border-color:   $gray-lighter !default;
-
-$nav-tabs-justified-link-border-color:            $gray-lighter !default;
-$nav-tabs-justified-active-link-border-color:     $body-bg !default;
-
-//== Pills
-$nav-pills-border-radius:                   $border-radius !default;
-$nav-pills-active-link-hover-bg:            $component-active-bg !default;
-$nav-pills-active-link-hover-color:         $component-active-color !default;
-
-
-//== Pagination
-//
-//##
-
-$pagination-color:                     #fff !default;
-$pagination-bg:                        $brand-success !default;
-$pagination-border:                    transparent !default;
-
-$pagination-border-color: $pagination-border;
-
-$pagination-hover-color:               #fff !default;
-$pagination-hover-bg:                  darken($brand-success, 15%) !default;
-$pagination-hover-border:              transparent !default;
-
-$pagination-active-color:              #fff !default;
-$pagination-active-bg:                 darken($brand-success, 15%) !default;
-$pagination-active-border:             transparent !default;
-
-$pagination-disabled-color:            $gray-lighter !default;
-$pagination-disabled-bg:               lighten($brand-success, 15%) !default;
-$pagination-disabled-border:           transparent !default;
-
-
-//== Pager
-//
-//##
-
-$pager-bg:                             $pagination-bg !default;
-$pager-border:                         $pagination-border !default;
-$pager-border-radius:                  15px !default;
-
-$pager-hover-bg:                       $pagination-hover-bg !default;
-
-$pager-active-bg:                      $pagination-active-bg !default;
-$pager-active-color:                   $pagination-active-color !default;
-
-$pager-disabled-color:                 #fff !default;
-
-
-//== Jumbotron
-//
-//##
-
-$jumbotron-padding:              30px !default;
-$jumbotron-color:                inherit !default;
-$jumbotron-bg:                   $gray-lighter !default;
-$jumbotron-heading-color:        inherit !default;
-$jumbotron-font-size:            ceil(($font-size-base * 1.5)) !default;
-$jumbotron-heading-font-size:    ceil(($font-size-base * 4.5)) !default;
-
-
-//== Form states and alerts
-//
-//## Define colors for form feedback states and, by default, alerts.
-
-$state-success-text:             #fff !default;
-$state-success-bg:               $brand-success !default;
-$state-success-border:           $brand-success !default;
-
-$state-info-text:                #fff !default;
-$state-info-bg:                  $brand-info !default;
-$state-info-border:              $brand-info !default;
-
-$state-warning-text:             #fff !default;
-$state-warning-bg:               $brand-warning !default;
-$state-warning-border:           $brand-warning !default;
-
-$state-danger-text:              #fff !default;
-$state-danger-bg:                $brand-danger !default;
-$state-danger-border:            $brand-danger !default;
-
-
-//== Tooltips
-//
-//##
-
-//** Tooltip max width
-$tooltip-max-width:           200px !default;
-//** Tooltip text color
-$tooltip-color:               #fff !default;
-//** Tooltip background color
-$tooltip-bg:                  #000 !default;
-$tooltip-opacity:             .9 !default;
-
-//** Tooltip arrow width
-$tooltip-arrow-width:         5px !default;
-//** Tooltip arrow color
-$tooltip-arrow-color:         $tooltip-bg !default;
-
-
-//== Popovers
-//
-//##
-
-//** Popover body background color
-$popover-bg:                          #fff !default;
-//** Popover maximum width
-$popover-max-width:                   276px !default;
-//** Popover border color
-$popover-border-color:                rgba(0,0,0,.2) !default;
-//** Popover fallback border color
-$popover-fallback-border-color:       #ccc !default;
-
-//** Popover title background color
-$popover-title-bg:                    darken($popover-bg, 3%) !default;
-
-//** Popover arrow width
-$popover-arrow-width:                 10px !default;
-//** Popover arrow color
-$popover-arrow-color:                 $popover-bg !default;
-
-//** Popover outer arrow width
-$popover-arrow-outer-width:           ($popover-arrow-width + 1) !default;
-//** Popover outer arrow color
-$popover-arrow-outer-color:           fadein($popover-border-color, 5%) !default;
-//** Popover outer arrow fallback color
-$popover-arrow-outer-fallback-color:  darken($popover-fallback-border-color, 20%) !default;
-
-
-//== Labels
-//
-//##
-
-//** Default label background color
-$tag-default-bg:            $btn-default-bg !default;
-//** Primary label background color
-$tag-primary-bg:            $brand-primary !default;
-//** Success label background color
-$tag-success-bg:            $brand-success !default;
-//** Info label background color
-$tag-info-bg:               $brand-info !default;
-//** Warning label background color
-$tag-warning-bg:            $brand-warning !default;
-//** Danger label background color
-$tag-danger-bg:             $brand-danger !default;
-
-//** Default label text color
-$tag-color:                 #fff !default;
-//** Default text color of a linked label
-$tag-link-hover-color:      #fff !default;
-
-
-//== Modals
-//
-//##
-
-//** Padding applied to the modal body
-$modal-inner-padding:         20px !default;
-
-//** Padding applied to the modal title
-$modal-title-padding:         15px !default;
-//** Modal title line-height
-$modal-title-line-height:     $line-height-base !default;
-
-//** Background color of modal content area
-$modal-content-bg:                             #fff !default;
-//** Modal content border color
-$modal-content-border-color:                   rgba(0,0,0,.2) !default;
-//** Modal content border color **for IE8**
-$modal-content-fallback-border-color:          #999 !default;
-
-//** Modal backdrop background color
-$modal-backdrop-bg:           #000 !default;
-//** Modal backdrop opacity
-$modal-backdrop-opacity:      .5 !default;
-//** Modal header border color
-$modal-header-border-color:   #e5e5e5 !default;
-//** Modal footer border color
-$modal-footer-border-color:   $modal-header-border-color !default;
-
-$modal-lg:                    900px !default;
-$modal-md:                    600px !default;
-$modal-sm:                    300px !default;
-
-
-//== Alerts
-//
-//## Define alert colors, border radius, and padding.
-
-$alert-padding:               15px !default;
-$alert-border-radius:         $border-radius !default;
-$alert-link-font-weight:      bold !default;
-
-$alert-success-bg:            $state-success-bg !default;
-$alert-success-text:          $state-success-text !default;
-$alert-success-border:        $state-success-border !default;
-
-$alert-info-bg:               $state-info-bg !default;
-$alert-info-text:             $state-info-text !default;
-$alert-info-border:           $state-info-border !default;
-
-$alert-warning-bg:            $state-warning-bg !default;
-$alert-warning-text:          $state-warning-text !default;
-$alert-warning-border:        $state-warning-border !default;
-
-$alert-danger-bg:             $state-danger-bg !default;
-$alert-danger-text:           $state-danger-text !default;
-$alert-danger-border:         $state-danger-border !default;
-
-
-//== Progress bars
-//
-//##
-
-//** Background color of the whole progress component
-$progress-bg:                 $gray-lighter !default;
-//** Progress bar text color
-$progress-bar-color:          #fff !default;
-//** Variable for setting rounded corners on progress bar.
-$progress-border-radius:      $border-radius !default;
-
-//** Default progress bar color
-$progress-bar-bg:             $brand-primary !default;
-//** Success progress bar color
-$progress-bar-success-bg:     $brand-success !default;
-//** Warning progress bar color
-$progress-bar-warning-bg:     $brand-warning !default;
-//** Danger progress bar color
-$progress-bar-danger-bg:      $brand-danger !default;
-//** Info progress bar color
-$progress-bar-info-bg:        $brand-info !default;
-
-
-//== List group
-//
-//##
-
-//** Background color on `.list-group-item`
-$list-group-bg:                 #fff !default;
-//** `.list-group-item` border color
-$list-group-border:             $gray-lighter !default;
-//** List group border radius
-$list-group-border-radius:      $border-radius !default;
-
-//** Background color of single list items on hover
-$list-group-hover-bg:           $gray-lighter !default;
-//** Text color of active list items
-$list-group-active-color:       $component-active-color !default;
-//** Background color of active list items
-$list-group-active-bg:          $component-active-bg !default;
-//** Border color of active list elements
-$list-group-active-border:      $list-group-active-bg !default;
-//** Text color for content within active list items
-$list-group-active-text-color:  lighten($list-group-active-bg, 40%) !default;
-
-//** Text color of disabled list items
-$list-group-disabled-color:      $gray-light !default;
-//** Background color of disabled list items
-$list-group-disabled-bg:         $gray-lighter !default;
-//** Text color for content within disabled list items
-$list-group-disabled-text-color: $list-group-disabled-color !default;
-
-$list-group-link-color:         #555 !default;
-$list-group-link-hover-color:   $list-group-link-color !default;
-$list-group-link-heading-color: #333 !default;
-
-
-//== Panels
-//
-//##
-
-$card-bg:                    #fff !default;
-$card-body-padding:          15px !default;
-$card-heading-padding:       10px 15px !default;
-$card-footer-padding:        $card-heading-padding !default;
-$card-border-radius:         $border-radius !default;
-
-//** Border color for elements within panels
-$card-inner-border:          $gray-lighter !default;
-$card-footer-bg:             $gray-lighter !default;
-
-$card-default-text:          $text-color !default;
-$card-default-border:        $gray-lighter !default;
-$card-default-heading-bg:    $gray-lighter !default;
-
-$card-primary-text:          #fff !default;
-$card-primary-border:        $brand-primary !default;
-$card-primary-heading-bg:    $brand-primary !default;
-
-$card-success-text:          $state-success-text !default;
-$card-success-border:        $state-success-border !default;
-$card-success-heading-bg:    $state-success-bg !default;
-
-$card-info-text:             $state-info-text !default;
-$card-info-border:           $state-info-border !default;
-$card-info-heading-bg:       $state-info-bg !default;
-
-$card-warning-text:          $state-warning-text !default;
-$card-warning-border:        $state-warning-border !default;
-$card-warning-heading-bg:    $state-warning-bg !default;
-
-$card-danger-text:           $state-danger-text !default;
-$card-danger-border:         $state-danger-border !default;
-$card-danger-heading-bg:     $state-danger-bg !default;
-
-
-//== Thumbnails
-//
-//##
-
-//** Padding around the thumbnail image
-$thumbnail-padding:           4px !default;
-//** Thumbnail background color
-$thumbnail-bg:                $body-bg !default;
-//** Thumbnail border color
-$thumbnail-border:            $gray-lighter !default;
-//** Thumbnail border radius
-$thumbnail-border-radius:     $border-radius !default;
-
-//** Custom text color for thumbnail captions
-$thumbnail-caption-color:     $text-color !default;
-//** Padding around the thumbnail caption
-$thumbnail-caption-padding:   9px !default;
-
-
-//== Wells
-//
-//##
-
-$well-bg:                     $gray-lighter !default;
-$well-border:                 transparent !default;
-
-
-//== Badges
-//
-//##
-
-$badge-color:                 #fff !default;
-//** Linked badge text color on hover
-$badge-link-hover-color:      #fff !default;
-$badge-bg:                    $brand-primary !default;
-
-//** Badge text color in active nav link
-$badge-active-color:          $brand-primary !default;
-//** Badge background color in active nav link
-$badge-active-bg:             #fff !default;
-
-$badge-font-weight:           bold !default;
-$badge-line-height:           1 !default;
-$badge-border-radius:         10px !default;
-
-
-//== Breadcrumbs
-//
-//##
-
-$breadcrumb-padding-y:   8px !default;
-$breadcrumb-padding-x: 15px !default;
-//** Breadcrumb background color
-$breadcrumb-bg:                 $gray-lighter !default;
-//** Breadcrumb text color
-$breadcrumb-color:              #ccc !default;
-//** Text color of current page in the breadcrumb
-$breadcrumb-active-color:       $gray !default;
-//** Textual separator for between breadcrumb elements
-$breadcrumb-separator:          "/" !default;
-
-
-//== Carousel
-//
-//##
-
-$carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6) !default;
-
-$carousel-control-color:                      #fff !default;
-$carousel-control-width:                      15% !default;
-$carousel-control-opacity:                    .5 !default;
-$carousel-control-font-size:                  20px !default;
-
-$carousel-indicator-active-bg:                #fff !default;
-$carousel-indicator-border-color:             #fff !default;
-
-$carousel-caption-color:                      #fff !default;
-
-
-//== Close
-//
-//##
-
-$close-font-weight:           bold !default;
-$close-color:                 #000 !default;
-$close-text-shadow:           none !default;
-
-
-//== Code
-//
-//##
-
-$code-color:                  #c7254e !default;
-$code-bg:                     #f9f2f4 !default;
-
-$kbd-color:                   #fff !default;
-$kbd-bg:                      #333 !default;
-
-$pre-bg:                      $gray-lighter !default;
-$pre-color:                   $gray-dark !default;
-$pre-border-color:            #ccc !default;
-$pre-scrollable-max-height:   340px !default;
-
-
-//== Type
-//
-//##
-
-//** Horizontal offset for forms and lists.
-$component-offset-x: 180px !default;
-//** Text muted color
-$text-muted:                  $gray-light !default;
-//** Abbreviations and acronyms border color
-$abbr-border-color:           $gray-light !default;
-//** Headings sm color
-$headings-sm-color:        $gray-light !default;
-//** Blockquote sm color
-$blockquote-sm-color:      $gray-light !default;
-//** Blockquote font size
-$blockquote-font-size:        ($font-size-base * 1.25) !default;
-//** Blockquote border color
-$blockquote-border-color:     $gray-lighter !default;
-//** Page header border color
-$page-header-border-color:    transparent !default;
-//** Width of x description list titles
-$dl-x-offset:        $component-offset-x !default;
-//** Point at which .dl-x becomes x
-$dl-x-breakpoint:    $grid-float-breakpoint !default;
-//** Horizontal line color.
-$hr-border:                   $gray-lighter !default;
-
-@import "moodle";
-
-@mixin placeholder($text) {
-    placeholder: $text;
-}
-@mixin box-shadow($text) {
-    box-shadow: $text;
-}
-@mixin transform($transforms) {
-    transform: $transforms;
-}
-@mixin rotate ($deg) {
-    @include transform(rotate(#{$deg}deg));
-}
-@mixin scale($scale) {
-    @include transform(scale($scale));
-}
-@mixin translate ($x, $y) {
-    @include transform(translate($x, $y));
-}
-@mixin skew ($x, $y) {
-    @include transform(skew(#{$x}deg, #{$y}deg));
-}
-@mixin transform-origin ($origin) {
-    transform-origin: $origin;
-}
-// Flatly 3.3.7
-// Bootswatch
-// -----------------------------------------------------
-
-$web-font-path: "https://fonts.googleapis.com/css?family=Lato:400,700,400italic" !default;
-@import url($web-font-path);
-
-// Navbar =====================================================================
-
-.navbar {
-  border-width: 0;
-
-  &-default {
-
-    .badge {
-      background-color: #fff;
-      color: $navbar-light-bg;
-    }
-  }
-
-  &-inverse {
-
-    .badge {
-      background-color: #fff;
-      color: $navbar-dark-bg;
-    }
-  }
-
-  &-brand {
-    line-height: 1;
-  }
-}
-
-// Buttons ====================================================================
-
-.btn {
-  border-width: 2px;
-}
-
-.btn:active {
-  @include box-shadow(none);
-}
-
-.btn-group.open .dropdown-toggle {
-  @include box-shadow(none);
-}
-
-// Typography =================================================================
-
-.text-primary,
-.text-primary:hover {
-  color: $brand-primary;
-}
-
-.text-success,
-.text-success:hover {
-  color: $brand-success;
-}
-
-.text-danger,
-.text-danger:hover {
-  color: $brand-danger;
-}
-
-.text-warning,
-.text-warning:hover {
-  color: $brand-warning;
-}
-
-.text-info,
-.text-info:hover {
-  color: $brand-info;
-}
-
-// Tables =====================================================================
-
-table,
-.table {
-
-  a:not(.btn) {
-    text-decoration: underline;
-  }
-
-  .dropdown-menu a {
-    text-decoration: none;
-  }
-
-  .success,
-  .warning,
-  .danger,
-  .info {
-    color: #fff;
-
-    > th > a,
-    > td > a,
-    > a {
-      color: #fff;
-    }
-  }
-
-  > thead > tr > th,
-  > tbody > tr > th,
-  > tfoot > tr > th,
-  > thead > tr > td,
-  > tbody > tr > td,
-  > tfoot > tr > td {
-    border: none;
-  }
-
-  &-bordered > thead > tr > th,
-  &-bordered > tbody > tr > th,
-  &-bordered > tfoot > tr > th,
-  &-bordered > thead > tr > td,
-  &-bordered > tbody > tr > td,
-  &-bordered > tfoot > tr > td {
-    border: 1px solid $table-border-color;
-  }
-}
-
-// Forms ======================================================================
-
-.form-control,
-input {
-  border-width: 2px;
-  @include box-shadow(none);
-
-  &:focus {
-    @include box-shadow(none);
-  }
-}
-
-.has-warning {
-  .help-block,
-  .control-label,
-  .radio,
-  .checkbox,
-  .radio-inline,
-  .checkbox-inline,
-  &.radio label,
-  &.checkbox label,
-  &.radio-inline label,
-  &.checkbox-inline label,
-  .form-control-feedback {
-    color: $brand-warning;
-  }
-
-  .form-control,
-  .form-control:focus {
-    border: 2px solid $brand-warning;
-  }
-
-  .input-group-addon {
-    border-color: $brand-warning;
-  }
-}
-
-.has-error {
-  .help-block,
-  .control-label,
-  .radio,
-  .checkbox,
-  .radio-inline,
-  .checkbox-inline,
-  &.radio label,
-  &.checkbox label,
-  &.radio-inline label,
-  &.checkbox-inline label,
-  .form-control-feedback {
-    color: $brand-danger;
-  }
-
-  .form-control,
-  .form-control:focus {
-    border: 2px solid $brand-danger;
-  }
-
-  .input-group-addon {
-    border-color: $brand-danger;
-  }
-}
-
-.has-success {
-  .help-block,
-  .control-label,
-  .radio,
-  .checkbox,
-  .radio-inline,
-  .checkbox-inline,
-  &.radio label,
-  &.checkbox label,
-  &.radio-inline label,
-  &.checkbox-inline label,
-  .form-control-feedback {
-    color: $brand-success;
-  }
-
-  .form-control,
-  .form-control:focus {
-    border: 2px solid $brand-success;
-  }
-
-  .input-group-addon {
-    border-color: $brand-success;
-  }
-}
-
-// Navs =======================================================================
-
-.nav {
-  .open > a,
-  .open > a:hover,
-  .open > a:focus {
-    border-color: transparent;
-  }
-}
-
-.pager {
-  a,
-  a:hover {
-    color: #fff;
-  }
-
-  .disabled {
-    &>a,
-    &>a:hover,
-    &>a:focus,
-    &>span {
-      background-color: $pagination-disabled-bg;
-    }
-  }
-}
-
-// Indicators =================================================================
-
-.close {
-  color: #fff;
-  text-decoration: none;
-  opacity: 0.4;
-
-  &:hover,
-  &:focus {
-    color: #fff;
-    opacity: 1;
-  }
-}
-
-.alert {
-
-  .alert-link {
-    color: #fff;
-    text-decoration: underline;
-  }
-}
-
-// Progress bars ==============================================================
-
-.progress {
-  height: 10px;
-  @include box-shadow(none);
-  .progress-bar {
-    font-size: 10px;
-    line-height: 10px;
-  }
-}
-
-// Containers =================================================================
-
-.well {
-  @include box-shadow(none);
-}
-
-a.list-group-item {
-
-  &.active,
-  &.active:hover,
-  &.active:focus {
-    border-color: $list-group-border;
-  }
-
-  &-success {
-    &.active {
-      background-color: $state-success-bg;
-    }
-
-    &.active:hover,
-    &.active:focus {
-      background-color: darken($state-success-bg, 5%);
-    }
-  }
-
-  &-warning {
-    &.active {
-      background-color: $state-warning-bg;
-    }
-    
-    &.active:hover,
-    &.active:focus {
-      background-color: darken($state-warning-bg, 5%);
-    }
-  }
-
-  &-danger {
-    &.active {
-      background-color: $state-danger-bg;
-    }
-    
-    &.active:hover,
-    &.active:focus {
-      background-color: darken($state-danger-bg, 5%);
-    }
-  }
-}
-
-.panel {
-  &-default {
-    .close {
-      color: $text-color;
-    }
-  }
-}
-
-.modal {
-  .close {
-    color: $text-color;
-  }
-}
-
-.popover {
-  color: $text-color;
-}
diff --git a/theme/boost/scss/preset-paper.scss b/theme/boost/scss/preset-paper.scss
deleted file mode 100644 (file)
index 7bf9c2b..0000000
+++ /dev/null
@@ -1,1555 +0,0 @@
-//
-// The MIT License (MIT)
-//
-// Copyright (c) 2013 Thomas Park
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-$bootstrap-sass-asset-helper: false !default;
-// Paper 3.3.7
-// Variables
-// --------------------------------------------------
-
-
-//== Colors
-//
-//## Gray and brand colors for use across Bootstrap.
-
-$gray-base:              #000 !default;
-$gray-darker:            lighten($gray-base, 13.5%) !default; // #222
-$gray-dark:              #212121 !default;
-$gray:                   #666 !default;
-$gray-light:             #bbb !default;
-$gray-lighter:           lighten($gray-base, 93.5%) !default; // #eee
-
-$gray-lightest:          lighten($gray-lighter, 13.5%);
-
-$brand-primary:         #2196F3 !default;
-$brand-success:         #4CAF50 !default;
-$brand-info:            #9C27B0 !default;
-$brand-warning:         #ff9800 !default;
-$brand-danger:          #e51c23 !default;
-
-
-//== Scaffolding
-//
-//## Settings for some of the most global styles.
-
-//** Background color for `<body>`.
-$body-bg:               #fff !default;
-//** Global text color on `<body>`.
-$text-color:            $gray !default;
-
-$body-color: $text-color;
-
-//** Global textual link color.
-$link-color:            $brand-primary !default;
-//** Link hover color set via `darken()` function.
-$link-hover-color:      darken($link-color, 15%) !default;
-//** Link hover decoration.
-$link-hover-decoration: underline !default;
-
-
-//== Typography
-//
-//## Font, line-height, and color for body text, headings, and more.
-
-$font-family-sans-serif:  "Roboto", "Helvetica Neue", Helvetica, Arial, sans-serif !default;
-$font-family-serif:       Georgia, "Times New Roman", Times, serif !default;
-//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
-$font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace !default;
-$font-family-base:        $font-family-sans-serif !default;
-
-$font-size-base:          13px !default;
-$font-size-root: $font-size-base;
-
-$font-size-lg:         ceil(($font-size-base * 1.25)) !default; // ~18px
-$font-size-sm:         ceil(($font-size-base * 0.85)) !default; // ~12px
-
-$font-size-h1:            56px !default;
-$font-size-h2:            45px !default;
-$font-size-h3:            34px !default;
-$font-size-h4:            24px !default;
-$font-size-h5:            20px !default;
-$font-size-h6:            14px !default;
-
-//** Unit-less `line-height` for use in components like buttons.
-$line-height-base:        1.846 !default; // 20/14
-//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
-$line-height-computed:    floor(($font-size-base * $line-height-base)) !default; // ~20px
-
-//** By default, this inherits from the `<body>`.
-$headings-font-family:    inherit !default;
-$headings-font-weight:    400 !default;
-$headings-line-height:    1.1 !default;
-$headings-color:          #444 !default;
-
-
-//== Iconography
-//
-//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
-
-//** Load fonts from this directory.
-$icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/") !default;
-//** File name for all font files.
-$icon-font-name:          "glyphicons-halflings-regular" !default;
-//** Element ID within SVG icon file.
-$icon-font-svg-id:        "glyphicons_halflingsregular" !default;
-
-
-//== Components
-//
-//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
-
-$padding-base-y:     6px !default;
-$padding-base-x:   16px !default;
-
-$padding-lg-y:    10px !default;
-$padding-lg-x:  16px !default;
-
-$padding-sm-y:    5px !default;
-$padding-sm-x:  10px !default;
-
-$padding-xs-y:       1px !default;
-$padding-xs-x:     5px !default;
-
-$line-height-lg:         1.3333333 !default; // extra decimals for Win 8.1 Chrome
-$line-height-sm:         1.5 !default;
-
-$border-radius:        3px !default;
-$border-radius-lg:       3px !default;
-$border-radius-sm:       3px !default;
-
-//** Global color for active items (e.g., navs or dropdowns).
-$component-active-color:    #fff !default;
-//** Global background color for active items (e.g., navs or dropdowns).
-$component-active-bg:       $brand-primary !default;
-
-//** Width of the `border` for generating carets that indicate dropdowns.
-$caret-width-base:          4px !default;
-//** Carets increase slightly in size for lgr components.
-$caret-width-lg:         5px !default;
-
-
-//== Tables
-//
-//## Customizes the `.table` component with basic values, each used across all table variations.
-
-//** Padding for `<th>`s and `<td>`s.
-$table-cell-padding:            8px !default;
-//** Padding for cells in `.table-condensed`.
-$table-sm-cell-padding:  5px !default;
-
-//** Default background color used for all tables.
-$table-bg:                      transparent !default;
-//** Background color used for `.table-striped`.
-$table-bg-accent:               #f9f9f9 !default;
-//** Background color used for `.table-hover`.
-$table-bg-hover:                #f5f5f5 !default;
-$table-bg-active:               $table-bg-hover !default;
-
-//** Border color for table and cell borders.
-$table-border-color:            #ddd !default;
-
-
-//== Buttons
-//
-//## For each of Bootstrap's buttons, define text, background and border color.
-
-$btn-font-weight:                normal !default;
-
-$btn-default-color:              #444 !default;
-$btn-default-bg:                 #fff !default;
-$btn-default-border:             transparent !default;
-
-$btn-secondary-color: $btn-default-color;
-$btn-secondary-bg: $btn-default-bg;
-$btn-secondary-border: $btn-default-border;
-
-
-
-$btn-primary-color:              #fff !default;
-$btn-primary-bg:                 $brand-primary !default;
-$btn-primary-border:             transparent !default;
-
-$btn-success-color:              #fff !default;
-$btn-success-bg:                 $brand-success !default;
-$btn-success-border:             transparent !default;
-
-$btn-info-color:                 #fff !default;
-$btn-info-bg:                    $brand-info !default;
-$btn-info-border:                transparent !default;
-
-$btn-warning-color:              #fff !default;
-$btn-warning-bg:                 $brand-warning !default;
-$btn-warning-border:             transparent !default;
-
-$btn-danger-color:               #fff !default;
-$btn-danger-bg:                  $brand-danger !default;
-$btn-danger-border:              transparent !default;
-
-$btn-link-disabled-color:        $gray-light !default;
-
-// Allows for customizing button radius independently from global border radius
-$btn-border-radius:         $border-radius !default;
-$btn-border-radius-lg:        $border-radius-lg !default;
-$btn-border-radius-sm:        $border-radius-sm !default;
-
-
-//== Forms
-//
-//##
-
-//** `<input>` background color
-$input-bg:                       transparent !default;
-//** `<input disabled>` background color
-$input-bg-disabled:              transparent !default;
-
-//** Text color for `<input>`s
-$input-color:                    $gray !default;
-//** `<input>` border color
-$input-border:                   transparent !default;
-
-// TODO: Rename `$input-border-radius` to `$input-border-radius` in v4
-//** Default `.form-control` border radius
-// This has no effect on `<select>`s in some browsers, due to the limited stylability of `<select>`s in CSS.
-$input-border-color: $input-border;
-
-$input-border-radius:            $border-radius !default;
-//** Large `.form-control` border radius
-$input-border-radius-lg:      $border-radius-lg !default;
-//** Small `.form-control` border radius
-$input-border-radius-sm:      $border-radius-sm !default;
-
-//** Border color for inputs on focus
-$input-border-focus:             #66afe9 !default;
-
-//** Placeholder text color
-$input-color-placeholder:        $gray-light !default;
-
-//** Default `.form-control` height
-$input-height:              ($line-height-computed + ($padding-base-y * 2) + 2) !default;
-//** Large `.form-control` height
-$input-height-lg:             (ceil($font-size-lg * $line-height-lg) + ($padding-lg-y * 2) + 2) !default;
-//** Small `.form-control` height
-$input-height-sm:             (floor($font-size-sm * $line-height-sm) + ($padding-sm-y * 2) + 2) !default;
-
-//** `.form-group` margin
-$form-group-margin-bottom:       15px !default;
-
-$legend-color:                   $gray-dark !default;
-$legend-border-color:            #e5e5e5 !default;
-
-//** Background color for textual input addons
-$input-group-addon-bg:           transparent !default;
-//** Border color for textual input addons
-$input-group-addon-border-color: $input-border !default;
-
-//** Disabled cursor for form controls and buttons.
-$cursor-disabled:                not-allowed !default;
-
-
-//== Dropdowns
-//
-//## Dropdown menu container and contents.
-
-//** Background for the dropdown menu.
-$dropdown-bg:                    #fff !default;
-//** Dropdown menu `border-color`.
-$dropdown-border:                rgba(0,0,0,.15) !default;
-//** Dropdown menu `border-color` **for IE8**.
-$dropdown-fallback-border:       #ccc !default;
-//** Divider color for between dropdown items.
-$dropdown-divider-bg:            #e5e5e5 !default;
-
-//** Dropdown link text color.
-$dropdown-link-color:            $text-color !default;
-//** Hover color for dropdown links.
-$dropdown-link-hover-color:      darken($gray-dark, 5%) !default;
-//** Hover background for dropdown links.
-$dropdown-link-hover-bg:         $gray-lighter !default;
-
-//** Active dropdown menu item text color.
-$dropdown-link-active-color:     $component-active-color !default;
-//** Active dropdown menu item background color.
-$dropdown-link-active-bg:        $component-active-bg !default;
-
-//** Disabled dropdown menu item background color.
-$dropdown-link-disabled-color:   $gray-light !default;
-
-//** Text color for headers within dropdown menus.
-$dropdown-header-color:          $gray-light !default;
-
-//** Deprecated `$dropdown-caret-color` as of v3.1.0
-$dropdown-caret-color:           $gray-light !default;
-
-
-//-- Z-index master list
-//
-// Warning: Avoid customizing these values. They're used for a bird's eye view
-// of components dependent on the z-axis and are designed to all work together.
-//
-// Note: These variables are not generated into the Customizer.
-
-$zindex-navbar:            1000 !default;
-$zindex-dropdown:          1000 !default;
-$zindex-popover:           1060 !default;
-$zindex-tooltip:           1070 !default;
-$zindex-navbar-fixed:      1030 !default;
-$zindex-modal-background:  1040 !default;
-$zindex-modal:             1050 !default;
-
-
-//== Media queries breakpoints
-//
-//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
-
-// Extra sm screen / phone
-//** Deprecated `$screen-xs` as of v3.0.1
-$screen-xs:                  480px !default;
-//** Deprecated `$screen-xs-min` as of v3.2.0
-$screen-xs-min:              $screen-xs !default;
-//** Deprecated `$screen-phone` as of v3.0.1
-$screen-phone:               $screen-xs-min !default;
-
-// Small screen / tablet
-//** Deprecated `$screen-sm` as of v3.0.1
-$screen-sm:                  768px !default;
-$screen-sm-min:              $screen-sm !default;
-//** Deprecated `$screen-tablet` as of v3.0.1
-$screen-tablet:              $screen-sm-min !default;
-
-// Medium screen / desktop
-//** Deprecated `$screen-md` as of v3.0.1
-$screen-md:                  992px !default;
-$screen-md-min:              $screen-md !default;
-//** Deprecated `$screen-desktop` as of v3.0.1
-$screen-desktop:             $screen-md-min !default;
-
-// Large screen / wide desktop
-//** Deprecated `$screen-lg` as of v3.0.1
-$screen-lg:                  1200px !default;
-$screen-lg-min:              $screen-lg !default;
-//** Deprecated `$screen-lg-desktop` as of v3.0.1
-$screen-lg-desktop:          $screen-lg-min !default;
-
-// So media queries don't overlap when required, provide a maximum
-$screen-xs-max:              ($screen-sm-min - 1) !default;
-$screen-sm-max:              ($screen-md-min - 1) !default;
-$screen-md-max:              ($screen-lg-min - 1) !default;
-
-
-//== Grid system
-//
-//## Define your custom responsive grid.
-
-//** Number of columns in the grid.
-$grid-columns:              12 !default;
-//** Padding between columns. Gets divided in half for the left and right.
-$grid-gutter-width:         30px !default;
-// Navbar collapse
-//** Point at which the navbar becomes uncollapsed.
-$grid-float-breakpoint:     $screen-sm-min !default;
-//** Point at which the navbar begins collapsing.
-$grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default;
-
-
-//== Container sizes
-//
-//## Define the maximum width of `.container` for different screen sizes.
-
-// Small screen / tablet
-$container-tablet:             (720px + $grid-gutter-width) !default;
-//** For `$screen-sm-min` and up.
-$container-sm:                 $container-tablet !default;
-
-// Medium screen / desktop
-$container-desktop:            (940px + $grid-gutter-width) !default;
-//** For `$screen-md-min` and up.
-$container-md:                 $container-desktop !default;
-
-// Large screen / wide desktop
-$container-lg-desktop:      (1140px + $grid-gutter-width) !default;
-//** For `$screen-lg-min` and up.
-$container-lg:                 $container-lg-desktop !default;
-
-
-//== Navbar
-//
-//##
-
-// Basics of a navbar
-$navbar-height:                    64px !default;
-$navbar-margin-bottom:             $line-height-computed !default;
-$navbar-border-radius:             $border-radius !default;
-$navbar-padding-x:        floor(($grid-gutter-width / 2)) !default;
-$navbar-padding-y:          (($navbar-height - $line-height-computed) / 2) !default;
-$navbar-collapse-max-height:       340px !default;
-
-$navbar-light-color:             $gray-light !default;
-$navbar-light-bg:                #fff !default;
-$navbar-light-border:            transparent !default;
-
-// Navbar links
-$navbar-light-link-color:                $gray !default;
-$navbar-light-link-hover-color:          $gray-dark !default;
-$navbar-light-link-hover-bg:             transparent !default;
-$navbar-light-link-active-color:         $gray-dark !default;
-$navbar-light-link-active-bg:            darken($navbar-light-bg, 6.5%) !default;
-$navbar-light-link-disabled-color:       #ccc !default;
-$navbar-light-link-disabled-bg:          transparent !default;
-
-// Navbar brand label
-$navbar-light-brand-color:               $navbar-light-link-color !default;
-$navbar-light-brand-hover-color:         $navbar-light-link-hover-color !default;
-$navbar-light-brand-hover-bg:            transparent !default;
-
-// Navbar toggle
-$navbar-light-toggle-hover-bg:           transparent !default;
-$navbar-light-toggle-icon-bar-bg:        rgba(0,0,0,0.5) !default;
-$navbar-light-toggle-border-color:       transparent !default;
-
-
-//=== Inverted navbar
-// Reset inverted navbar basics
-$navbar-dark-color:                      $gray-light !default;
-$navbar-dark-bg:                         $brand-primary !default;
-$navbar-dark-border:                     transparent !default;
-
-// Inverted navbar links
-$navbar-dark-link-color:                 lighten($brand-primary, 30%) !default;
-$navbar-dark-link-hover-color:           #fff !default;
-$navbar-dark-link-hover-bg:              transparent !default;
-$navbar-dark-link-active-color:          $navbar-dark-link-hover-color !default;
-$navbar-dark-link-active-bg:             darken($navbar-dark-bg, 10%) !default;
-$navbar-dark-link-disabled-color:        #444 !default;
-$navbar-dark-link-disabled-bg:           transparent !default;
-
-// Inverted navbar brand label
-$navbar-dark-brand-color:                $navbar-dark-link-color !default;
-$navbar-dark-brand-hover-color:          #fff !default;
-$navbar-dark-brand-hover-bg:             transparent !default;
-
-// Inverted navbar toggle\
-$navbar-dark-toggle-hover-bg:            transparent !default;
-$navbar-dark-toggle-icon-bar-bg:         rgba(0,0,0,0.5) !default;
-$navbar-dark-toggle-border-color:        transparent !default;
-
-
-//== Navs
-//
-//##
-
-//=== Shared nav styles
-$nav-link-padding:                          10px 15px !default;
-$nav-link-hover-bg:                         $gray-lighter !default;
-
-$nav-disabled-link-color:                   $gray-light !default;
-$nav-disabled-link-hover-color:             $gray-light !default;
-
-//== Tabs
-$nav-tabs-border-color:                     transparent !default;
-
-$nav-tabs-link-hover-border-color:          $gray-lighter !default;
-
-$nav-tabs-active-link-hover-bg:             transparent !default;
-$nav-tabs-active-link-hover-color:          $gray !default;
-$nav-tabs-active-link-hover-border-color:   transparent !default;
-
-$nav-tabs-justified-link-border-color:            $nav-tabs-border-color !default;
-$nav-tabs-justified-active-link-border-color:     $body-bg !default;
-
-//== Pills
-$nav-pills-border-radius:                   $border-radius !default;
-$nav-pills-active-link-hover-bg:            $component-active-bg !default;
-$nav-pills-active-link-hover-color:         $component-active-color !default;
-
-
-//== Pagination
-//
-//##
-
-$pagination-color:                     $link-color !default;
-$pagination-bg:                        #fff !default;
-$pagination-border:                    #ddd !default;
-
-$pagination-border-color: $pagination-border;
-
-$pagination-hover-color:               $link-hover-color !default;
-$pagination-hover-bg:                  $gray-lighter !default;
-$pagination-hover-border:              #ddd !default;
-
-$pagination-active-color:              #fff !default;
-$pagination-active-bg:                 $brand-primary !default;
-$pagination-active-border:             $brand-primary !default;
-
-$pagination-disabled-color:            $gray-light !default;
-$pagination-disabled-bg:               #fff !default;
-$pagination-disabled-border:           #ddd !default;
-
-
-//== Pager
-//
-//##
-
-$pager-bg:                             $pagination-bg !default;
-$pager-border:                         $pagination-border !default;
-$pager-border-radius:                  15px !default;
-
-$pager-hover-bg:                       $pagination-hover-bg !default;
-
-$pager-active-bg:                      $pagination-active-bg !default;
-$pager-active-color:                   $pagination-active-color !default;
-
-$pager-disabled-color:                 $pagination-disabled-color !default;
-
-
-//== Jumbotron
-//
-//##
-
-$jumbotron-padding:              30px !default;
-$jumbotron-color:                inherit !default;
-$jumbotron-bg:                   #f5f5f5 !default;
-$jumbotron-heading-color:        $headings-color !default;
-$jumbotron-font-size:            ceil(($font-size-base * 1.5)) !default;
-$jumbotron-heading-font-size:    ceil(($font-size-base * 4.5)) !default;
-
-
-//== Form states and alerts
-//
-//## Define colors for form feedback states and, by default, alerts.
-
-$state-success-text:             $brand-success !default;
-$state-success-bg:               #dff0d8 !default;
-$state-success-border:           darken(adjust-hue($state-success-bg, -10), 5%) !default;
-
-$state-info-text:                $brand-info !default;
-$state-info-bg:                  #e1bee7 !default;
-$state-info-border:              darken(adjust-hue($state-info-bg, -10), 7%) !default;
-
-$state-warning-text:             $brand-warning !default;
-$state-warning-bg:               #ffe0b2 !default;
-$state-warning-border:           darken(adjust-hue($state-warning-bg, -10), 5%) !default;
-
-$state-danger-text:              $brand-danger !default;
-$state-danger-bg:                #f9bdbb !default;
-$state-danger-border:            darken(adjust-hue($state-danger-bg, -10), 5%) !default;
-
-
-//== Tooltips
-//
-//##
-
-//** Tooltip max width
-$tooltip-max-width:           200px !default;
-//** Tooltip text color
-$tooltip-color:               #fff !default;
-//** Tooltip background color
-$tooltip-bg:                  #727272 !default;
-$tooltip-opacity:             .9 !default;
-
-//** Tooltip arrow width
-$tooltip-arrow-width:         5px !default;
-//** Tooltip arrow color
-$tooltip-arrow-color:         $tooltip-bg !default;
-
-
-//== Popovers
-//
-//##
-
-//** Popover body background color
-$popover-bg:                          #fff !default;
-//** Popover maximum width
-$popover-max-width:                   276px !default;
-//** Popover border color
-$popover-border-color:                transparent !default;
-//** Popover fallback border color
-$popover-fallback-border-color:       transparent !default;
-
-//** Popover title background color
-$popover-title-bg:                    darken($popover-bg, 3%) !default;
-
-//** Popover arrow width
-$popover-arrow-width:                 10px !default;
-//** Popover arrow color
-$popover-arrow-color:                 $popover-bg !default;
-
-//** Popover outer arrow width
-$popover-arrow-outer-width:           ($popover-arrow-width + 1) !default;
-//** Popover outer arrow color
-$popover-arrow-outer-color:           fadein($popover-border-color, 12%) !default;
-//** Popover outer arrow fallback color
-$popover-arrow-outer-fallback-color:  darken($popover-fallback-border-color, 20%) !default;
-
-
-//== Labels
-//
-//##
-
-//** Default label background color
-$tag-default-bg:            $gray-light !default;
-//** Primary label background color
-$tag-primary-bg:            $brand-primary !default;
-//** Success label background color
-$tag-success-bg:            $brand-success !default;
-//** Info label background color
-$tag-info-bg:               $brand-info !default;
-//** Warning label background color
-$tag-warning-bg:            $brand-warning !default;
-//** Danger label background color
-$tag-danger-bg:             $brand-danger !default;
-
-//** Default label text color
-$tag-color:                 #fff !default;
-//** Default text color of a linked label
-$tag-link-hover-color:      #fff !default;
-
-
-//== Modals
-//
-//##
-
-//** Padding applied to the modal body
-$modal-inner-padding:         15px !default;
-
-//** Padding applied to the modal title
-$modal-title-padding:         15px !default;
-//** Modal title line-height
-$modal-title-line-height:     $line-height-base !default;
-
-//** Background color of modal content area
-$modal-content-bg:                             #fff !default;
-//** Modal content border color
-$modal-content-border-color:                   transparent !default;
-//** Modal content border color **for IE8**
-$modal-content-fallback-border-color:          #999 !default;
-
-//** Modal backdrop background color
-$modal-backdrop-bg:           #000 !default;
-//** Modal backdrop opacity
-$modal-backdrop-opacity:      .5 !default;
-//** Modal header border color
-$modal-header-border-color:   transparent !default;
-//** Modal footer border color
-$modal-footer-border-color:   $modal-header-border-color !default;
-
-$modal-lg:                    900px !default;
-$modal-md:                    600px !default;
-$modal-sm:                    300px !default;
-
-
-//== Alerts
-//
-//## Define alert colors, border radius, and padding.
-
-$alert-padding:               15px !default;
-$alert-border-radius:         $border-radius !default;
-$alert-link-font-weight:      bold !default;
-
-$alert-success-bg:            $state-success-bg !default;
-$alert-success-text:          $state-success-text !default;
-$alert-success-border:        $state-success-border !default;
-
-$alert-info-bg:               $state-info-bg !default;
-$alert-info-text:             $state-info-text !default;
-$alert-info-border:           $state-info-border !default;
-
-$alert-warning-bg:            $state-warning-bg !default;
-$alert-warning-text:          $state-warning-text !default;
-$alert-warning-border:        $state-warning-border !default;
-
-$alert-danger-bg:             $state-danger-bg !default;
-$alert-danger-text:           $state-danger-text !default;
-$alert-danger-border:         $state-danger-border !default;
-
-
-//== Progress bars
-//
-//##
-
-//** Background color of the whole progress component
-$progress-bg:                 #f5f5f5 !default;
-//** Progress bar text color
-$progress-bar-color:          #fff !default;
-//** Variable for setting rounded corners on progress bar.
-$progress-border-radius:      $border-radius !default;
-
-//** Default progress bar color
-$progress-bar-bg:             $brand-primary !default;
-//** Success progress bar color
-$progress-bar-success-bg:     $brand-success !default;
-//** Warning progress bar color
-$progress-bar-warning-bg:     $brand-warning !default;
-//** Danger progress bar color
-$progress-bar-danger-bg:      $brand-danger !default;
-//** Info progress bar color
-$progress-bar-info-bg:        $brand-info !default;
-
-
-//== List group
-//
-//##
-
-//** Background color on `.list-group-item`
-$list-group-bg:                 #fff !default;
-//** `.list-group-item` border color
-$list-group-border:             #ddd !default;
-//** List group border radius
-$list-group-border-radius:      $border-radius !default;
-
-//** Background color of single list items on hover
-$list-group-hover-bg:           #f5f5f5 !default;
-//** Text color of active list items
-$list-group-active-color:       $component-active-color !default;
-//** Background color of active list items
-$list-group-active-bg:          $component-active-bg !default;
-//** Border color of active list elements
-$list-group-active-border:      $list-group-active-bg !default;
-//** Text color for content within active list items
-$list-group-active-text-color:  lighten($list-group-active-bg, 40%) !default;
-
-//** Text color of disabled list items
-$list-group-disabled-color:      $gray-light !default;
-//** Background color of disabled list items
-$list-group-disabled-bg:         $gray-lighter !default;
-//** Text color for content within disabled list items
-$list-group-disabled-text-color: $list-group-disabled-color !default;
-
-$list-group-link-color:         #555 !default;
-$list-group-link-hover-color:   $list-group-link-color !default;
-$list-group-link-heading-color: #333 !default;
-
-
-//== Panels
-//
-//##
-
-$card-bg:                    #fff !default;
-$card-body-padding:          15px !default;
-$card-heading-padding:       10px 15px !default;
-$card-footer-padding:        $card-heading-padding !default;
-$card-border-radius:         $border-radius !default;
-
-//** Border color for elements within panels
-$card-inner-border:          #ddd !default;
-$card-footer-bg:             #f5f5f5 !default;
-
-$card-default-text:          $gray-dark !default;
-$card-default-border:        #ddd !default;
-$card-default-heading-bg:    #f5f5f5 !default;
-
-$card-primary-text:          #fff !default;
-$card-primary-border:        $brand-primary !default;
-$card-primary-heading-bg:    $brand-primary !default;
-
-$card-success-text:          #fff !default;
-$card-success-border:        $state-success-border !default;
-$card-success-heading-bg:    $brand-success !default;
-
-$card-info-text:             #fff !default;
-$card-info-border:           $state-info-border !default;
-$card-info-heading-bg:       $brand-info !default;
-
-$card-warning-text:          #fff !default;
-$card-warning-border:        $state-warning-border !default;
-$card-warning-heading-bg:    $brand-warning !default;
-
-$card-danger-text:           #fff !default;
-$card-danger-border:         $state-danger-border !default;
-$card-danger-heading-bg:     $brand-danger !default;
-
-
-//== Thumbnails
-//
-//##
-
-//** Padding around the thumbnail image
-$thumbnail-padding:           4px !default;
-//** Thumbnail background color
-$thumbnail-bg:                $body-bg !default;
-//** Thumbnail border color
-$thumbnail-border:            #ddd !default;
-//** Thumbnail border radius
-$thumbnail-border-radius:     $border-radius !default;
-
-//** Custom text color for thumbnail captions
-$thumbnail-caption-color:     $text-color !default;
-//** Padding around the thumbnail caption
-$thumbnail-caption-padding:   9px !default;
-
-
-//== Wells
-//
-//##
-
-$well-bg:                     #f5f5f5 !default;
-$well-border:                 transparent !default;
-
-
-//== Badges
-//
-//##
-
-$badge-color:                 #fff !default;
-//** Linked badge text color on hover
-$badge-link-hover-color:      #fff !default;
-$badge-bg:                    $gray-light !default;
-
-//** Badge text color in active nav link
-$badge-active-color:          $link-color !default;
-//** Badge background color in active nav link
-$badge-active-bg:             #fff !default;
-
-$badge-font-weight:           normal !default;
-$badge-line-height:           1 !default;
-$badge-border-radius:         10px !default;
-
-
-//== Breadcrumbs
-//
-//##
-
-$breadcrumb-padding-y:   8px !default;
-$breadcrumb-padding-x: 15px !default;
-//** Breadcrumb background color
-$breadcrumb-bg:                 #f5f5f5 !default;
-//** Breadcrumb text color
-$breadcrumb-color:              #ccc !default;
-//** Text color of current page in the breadcrumb
-$breadcrumb-active-color:       $gray-light !default;
-//** Textual separator for between breadcrumb elements
-$breadcrumb-separator:          "/" !default;
-
-
-//== Carousel
-//
-//##
-
-$carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6) !default;
-
-$carousel-control-color:                      #fff !default;
-$carousel-control-width:                      15% !default;
-$carousel-control-opacity:                    .5 !default;
-$carousel-control-font-size:                  20px !default;
-
-$carousel-indicator-active-bg:                #fff !default;
-$carousel-indicator-border-color:             #fff !default;
-
-$carousel-caption-color:                      #fff !default;
-
-
-//== Close
-//
-//##
-
-$close-font-weight:           normal !default;
-$close-color:                 #000 !default;
-$close-text-shadow:           none !default;
-
-
-//== Code
-//
-//##
-
-$code-color:                  #c7254e !default;
-$code-bg:                     #f9f2f4 !default;
-
-$kbd-color:                   #fff !default;
-$kbd-bg:                      #333 !default;
-
-$pre-bg:                      #f5f5f5 !default;
-$pre-color:                   $gray-dark !default;
-$pre-border-color:            #ccc !default;
-$pre-scrollable-max-height:   340px !default;
-
-
-//== Type
-//
-//##
-
-//** Horizontal offset for forms and lists.
-$component-offset-x: 180px !default;
-//** Text muted color
-$text-muted:                  $gray-light !default;
-//** Abbreviations and acronyms border color
-$abbr-border-color:           $gray-light !default;
-//** Headings sm color
-$headings-sm-color:        $gray-light !default;
-//** Blockquote sm color
-$blockquote-sm-color:      $gray-light !default;
-//** Blockquote font size
-$blockquote-font-size:        ($font-size-base * 1.25) !default;
-//** Blockquote border color
-$blockquote-border-color:     $gray-lighter !default;
-//** Page header border color
-$page-header-border-color:    $gray-lighter !default;
-//** Width of x description list titles
-$dl-x-offset:        $component-offset-x !default;
-//** Point at which .dl-x becomes x
-$dl-x-breakpoint:    $grid-float-breakpoint !default;
-//** Horizontal line color.
-$hr-border:                   $gray-lighter !default;
-
-@import "moodle";
-
-@mixin placeholder($text) {
-    placeholder: $text;
-}
-@mixin box-shadow($text) {
-    box-shadow: $text;
-}
-@mixin transform($transforms) {
-    transform: $transforms;
-}
-@mixin rotate ($deg) {
-    @include transform(rotate(#{$deg}deg));
-}
-@mixin scale($scale) {
-    @include transform(scale($scale));
-}
-@mixin translate ($x, $y) {
-    @include transform(translate($x, $y));
-}
-@mixin skew ($x, $y) {
-    @include transform(skew(#{$x}deg, #{$y}deg));
-}
-@mixin transform-origin ($origin) {
-    transform-origin: $origin;
-}
-// Paper 3.3.7
-// Bootswatch
-// -----------------------------------------------------
-
-$web-font-path: "https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" !default;
-@import url($web-font-path);
-
-// Navbar =====================================================================
-
-.navbar {
-  border: none;
-  @include box-shadow(0 1px 2px rgba(0,0,0,.3));
-
-  &-brand {
-    font-size: 24px;
-  }
-
-  &-inverse {
-    .navbar-form {
-
-      input[type=text],
-      input[type=password] {
-        color: #fff;
-        @include box-shadow(inset 0 -1px 0 $navbar-dark-link-color);
-        @include placeholder($navbar-dark-link-color);
-
-        &:focus {
-          @include box-shadow(inset 0 -2px 0 #fff);
-        }
-      }
-    }
-  }
-}
-
-// Buttons ====================================================================
-
-@mixin btn($class,$bg){
-  .btn-#{$class} {
-    background-size: 200% 200%;
-    background-position: 50%;
-
-    &:focus {
-      background-color: $bg;
-    }
-
-    &:hover,
-    &:active:hover {
-      background-color: darken($bg, 6%);
-    }
-
-    &:active {
-      background-color: darken($bg, 12%);
-      @include gradient-radial(darken($bg, 12%) 10%, $bg 11%);
-      background-size: 1000% 1000%;
-      @include box-shadow(2px 2px 4px rgba(0,0,0,.4));
-    }
-  }
-}
-
-@include btn(default,$btn-default-bg);
-@include btn(primary,$btn-primary-bg);
-@include btn(success,$btn-success-bg);
-@include btn(info,$btn-info-bg);
-@include btn(warning,$btn-warning-bg);
-@include btn(danger,$btn-danger-bg);
-@include btn(link,#fff);
-
-.btn {
-  text-transform: uppercase;
-  border: none;
-  @include box-shadow(1px 1px 4px rgba(0,0,0,.4));
-  @include transition(all 0.4s);
-
-  &-link {
-    border-radius: $btn-border-radius;
-    @include box-shadow(none);
-    color: $btn-default-color;
-
-    &:hover,
-    &:focus {
-      @include box-shadow(none);
-      color: $btn-default-color;
-      text-decoration: none;
-    }
-  }
-
-  &-default {
-
-    &.disabled {
-      background-color: rgba(0, 0, 0, 0.1);
-      color: rgba(0, 0, 0, 0.4);
-      opacity: 1;
-    }
-  }
-}
-
-.btn-group {
-  .btn + .btn,
-  .btn + .btn-group,
-  .btn-group + .btn,
-  .btn-group + .btn-group {
-    margin-left: 0;
-  }
-
-  &-y {
-    > .btn + .btn,
-    > .btn + .btn-group,
-    > .btn-group + .btn,
-    > .btn-group + .btn-group {
-      margin-top: 0;
-    }
-  }
-}
-
-// Typography =================================================================
-
-body {
-  -webkit-font-smoothing: antialiased;
-  letter-spacing: .1px;
-}
-
-p {
-  margin: 0 0 1em;
-}
-
-input,
-button {
-  -webkit-font-smoothing: antialiased;
-  letter-spacing: .1px;
-}
-
-a {
-  @include transition(all 0.2s);
-}
-
-// Tables =====================================================================
-
-.table-hover {
-  > tbody > tr,
-  > tbody > tr > th,
-  > tbody > tr > td {
-    @include transition(all 0.2s);
-  }
-}
-
-// Forms ======================================================================
-
-label {
-  font-weight: normal;
-}
-
-textarea,
-textarea.form-control,
-input.form-control,
-input[type=text],
-input[type=password],
-input[type=email],
-input[type=number],
-[type=text].form-control,
-[type=password].form-control,
-[type=email].form-control,
-[type=tel].form-control,
-[contenteditable].form-control {
-  padding: 0;
-  border: none;
-  border-radius: 0;
-  -webkit-appearance: none;
-  @include box-shadow(inset 0 -1px 0 #ddd);
-  font-size: 16px;
-
-  &:focus {
-    @include box-shadow(inset 0 -2px 0 $brand-primary);
-  }
-
-  &[disabled],
-  &[readonly] {
-    @include box-shadow(none);
-    border-bottom: 1px dotted #ddd;
-  }
-
-  &.input {
-    &-sm {
-      font-size: $font-size-sm;
-    }
-
-    &-lg {
-      font-size: $font-size-lg;
-    }
-  }
-}
-
-select,
-select.form-control {
-  border: 0;
-  border-radius: 0;
-  -webkit-appearance: none;
-  -moz-appearance: none;
-  appearance: none;
-  padding-left: 0;
-  padding-right: 0\9; // remove padding for < ie9 since default arrow can't be removed
-  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAAJ1BMVEVmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmaP/QSjAAAADHRSTlMAAgMJC0uWpKa6wMxMdjkoAAAANUlEQVR4AeXJyQEAERAAsNl7Hf3X6xt0QL6JpZWq30pdvdadme+0PMdzvHm8YThHcT1H7K0BtOMDniZhWOgAAAAASUVORK5CYII=);
-  background-size: 13px;
-  background-repeat: no-repeat;
-  background-position: right center;
-  @include box-shadow(inset 0 -1px 0 #ddd);
-  font-size: 16px;
-  line-height: 1.5;
-
-  &::-ms-expand {
-    display: none;
-  }
-
-  &.input {
-    &-sm {
-      font-size: $font-size-sm;
-    }
-
-    &-lg {
-      font-size: $font-size-lg;
-    }
-  }
-
-  &:focus {
-    @include box-shadow(inset 0 -2px 0 $brand-primary);
-    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAAJ1BMVEUhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF8S9ewAAAADHRSTlMAAgMJC0uWpKa6wMxMdjkoAAAANUlEQVR4AeXJyQEAERAAsNl7Hf3X6xt0QL6JpZWq30pdvdadme+0PMdzvHm8YThHcT1H7K0BtOMDniZhWOgAAAAASUVORK5CYII=);
-  }
-
-  &[multiple] {
-    background: none;
-  }
-}
-
-.radio,
-.radio-inline,
-.checkbox,
-.checkbox-inline {
-  label {
-    padding-left: 25px;
-  }
-
-  input[type="radio"],
-  input[type="checkbox"] {
-    margin-left: -25px;
-  }
-}
-
-input[type="radio"],
-.radio input[type="radio"],
-.radio-inline input[type="radio"] {
-  position: relative;
-  margin-top: 6px;
-  margin-right: 4px;
-  y-align: top;
-  border: none;
-  background-color: transparent;
-  -webkit-appearance: none;
-  appearance: none;
-  cursor: pointer;
-
-  &:focus {
-    outline: none;
-  }
-
-  &:before,
-  &:after {
-    content: "";
-    display: block;
-    width: 18px;
-    height: 18px;
-    border-radius: 50%;
-    @include transition(240ms);
-  }
-
-  &:before {
-    position: absolute;
-    left: 0;
-    top: -3px;
-    background-color: $brand-primary;
-    @include scale(0);
-  }
-
-  &:after {
-    position: relative;
-    top: -3px;
-    border: 2px solid $gray;
-  }
-
-  &:checked:before {
-    @include scale(0.5);
-  }
-
-  &:disabled:checked:before {
-    background-color: $gray-light;
-  }
-
-  &:checked:after {
-    border-color: $brand-primary;
-  }
-
-  &:disabled:after,
-  &:disabled:checked:after {
-    border-color: $gray-light;
-  }
-}
-
-input[type="checkbox"],
-.checkbox input[type="checkbox"],
-.checkbox-inline input[type="checkbox"] {
-  position: relative;
-  border: none;
-  margin-bottom: -4px;
-  -webkit-appearance: none;
-  appearance: none;
-  cursor: pointer;
-
-  &:focus {
-    outline: none;
-  }
-
-  &:focus:after {
-    border-color: $brand-primary;
-  }
-
-  &:after {
-    content: "";
-    display: block;
-    width: 18px;
-    height: 18px;
-    margin-top: -2px;
-    margin-right: 5px;
-    border: 2px solid $gray;
-    border-radius: 2px;
-    @include transition(240ms);
-  }
-
-  &:checked:before {
-    content: "";
-    position: absolute;
-    top: 0;
-    left: 6px;
-    display: table;
-    width: 6px;
-    height: 12px;
-    border: 2px solid #fff;
-    border-top-width: 0;
-    border-left-width: 0;
-    @include rotate(45deg);
-  }
-
-  &:checked:after {
-    background-color: $brand-primary;
-    border-color: $brand-primary;
-  }
-
-  &:disabled:after {
-    border-color: $gray-light;
-  }
-
-  &:disabled:checked:after {
-    background-color: $gray-light;
-    border-color: transparent;
-  }
-}
-
-.has-warning {
-  input:not([type=checkbox]),
-  .form-control,
-  input.form-control[readonly],
-  input[type=text][readonly],
-  [type=text].form-control[readonly],
-  input:not([type=checkbox]):focus,
-  .form-control:focus {
-    border-bottom: none;
-    @include box-shadow(inset 0 -2px 0 $brand-warning);
-  }
-}
-
-.has-error {
-  input:not([type=checkbox]),
-  .form-control,
-  input.form-control[readonly],
-  input[type=text][readonly],
-  [type=text].form-control[readonly],
-  input:not([type=checkbox]):focus,
-  .form-control:focus {
-    border-bottom: none;
-    @include box-shadow(inset 0 -2px 0 $brand-danger);
-  }
-}
-
-.has-success {
-  input:not([type=checkbox]),
-  .form-control,
-  input.form-control[readonly],
-  input[type=text][readonly],
-  [type=text].form-control[readonly],
-  input:not([type=checkbox]):focus,
-  .form-control:focus {
-    border-bottom: none;
-    @include box-shadow(inset 0 -2px 0 $brand-success);
-  }
-}
-
-// Remove the Bootstrap feedback styles for input addons
-.input-group-addon {
-  .has-warning &, .has-error &, .has-success & {
-    color: $input-color;
-    border-color: $input-group-addon-border-color;
-    background-color: $input-group-addon-bg;
-  }
-}
-
-.form-group-lg {
-  select,
-  select.form-control {
-    line-height: 1.5;
-  }
-}
-
-// Navs =======================================================================
-
-.nav-tabs {
-  > li > a,
-  > li > a:focus {
-    margin-right: 0;
-    background-color: transparent;
-    border: none;
-    color: $navbar-light-link-color;
-    @include box-shadow(inset 0 -1px 0 #ddd);
-    @include transition(all 0.2s);
-
-    &:hover {
-      background-color: transparent;
-      @include box-shadow(inset 0 -2px 0 $brand-primary);
-      color: $brand-primary;
-    }
-  }
-
-  & > li.active > a,
-  & > li.active > a:focus {
-    border: none;
-    @include box-shadow(inset 0 -2px 0 $brand-primary);
-    color: $brand-primary;
-
-    &:hover {
-      border: none;
-      color: $brand-primary;
-    }
-  }
-
-  & > li.disabled > a {
-    @include box-shadow(inset 0 -1px 0 #ddd);
-  }
-
-  &.nav-justified {
-
-    & > li > a,
-    & > li > a:hover,
-    & > li > a:focus,
-    & > .active > a,
-    & > .active > a:hover,
-    & > .active > a:focus {
-      border: none;
-    }
-  }
-
-  .dropdown-menu {
-    margin-top: 0;
-  }
-}
-
-.dropdown-menu {
-  margin-top: 0;
-  border: none;
-  @include box-shadow(0 1px 4px rgba(0,0,0,.3));
-}
-
-// Indicators =================================================================
-
-.alert {
-  border: none;
-  color: #fff;
-
-  &-success {
-    background-color: $brand-success;
-  }
-
-  &-info {
-    background-color: $brand-info;
-  }
-
-  &-warning {
-    background-color: $brand-warning;
-  }
-
-  &-danger {
-    background-color: $brand-danger;
-  }
-
-  a:not(.close):not(.btn),
-  .alert-link {
-    color: #fff;
-    font-weight: bold;
-  }
-
-  .close {
-    color: #fff;
-  }
-}
-
-.badge {
-  padding: 4px 6px 4px;
-}
-
-.progress {
-  position: relative;
-  z-index: 1;
-  height: 6px;
-  border-radius: 0;
-
-  @include box-shadow(none);
-
-  &-bar {
-    @include box-shadow(none);
-
-    &:last-child {
-      border-radius: 0 3px 3px 0;
-    }
-
-    &:last-child {
-      &:before {
-        display: block;
-        content: "";
-        position: absolute;
-        width: 100%;
-        height: 100%;
-        left: 0;
-        right: 0;
-        z-index: -1;
-        background-color: lighten($progress-bar-bg, 35%);
-      }
-    }
-
-    &-success:last-child.progress-bar:before {
-      background-color: lighten($brand-success, 35%);
-    }
-
-    &-info:last-child.progress-bar:before {
-      background-color: lighten($brand-info, 45%);
-    }
-    &-warning:last-child.progress-bar:before {
-      background-color: lighten($brand-warning, 35%);
-    }
-
-    &-danger:last-child.progress-bar:before {
-      background-color: lighten($brand-danger, 25%);
-    }
-  }
-}
-
-// Progress bars ==============================================================
-
-// Containers =================================================================
-
-.close {
-  font-size: 34px;
-  font-weight: 300;
-  line-height: 24px;
-  opacity: 0.6;
-  @include transition(all 0.2s);
-
-  &:hover {
-    opacity: 1;
-  }
-}
-
-.list-group {
-
-  &-item {
-    padding: 15px;
-  }
-
-  &-item-text {
-    color: $gray-light;
-  }
-}
-
-.well {
-  border-radius: 0;
-  @include box-shadow(none);
-}
-
-.panel {
-  border: none;
-  border-radius: 2px;
-  @include box-shadow(0 1px 4px rgba(0,0,0,.3));
-
-  &-heading {
-    border-bottom: none;
-  }
-
-  &-footer {
-    border-top: none;
-  }
-}
-
-.popover {
-  border: none;
-  @include box-shadow(0 1px 4px rgba(0,0,0,.3));
-}
-
-.carousel {
-  &-caption {
-    h1, h2, h3, h4, h5, h6 {
-      color: inherit;
-    }
-  }
-}
-
diff --git a/theme/boost/scss/preset-readable.scss b/theme/boost/scss/preset-readable.scss
deleted file mode 100644 (file)
index eeadb4d..0000000
+++ /dev/null
@@ -1,1119 +0,0 @@
-//
-// The MIT License (MIT)
-//
-// Copyright (c) 2013 Thomas Park
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-$bootstrap-sass-asset-helper: false !default;
-// Readable 3.3.7
-// Variables
-// --------------------------------------------------
-
-
-//== Colors
-//
-//## Gray and brand colors for use across Bootstrap.
-
-$gray-base:              #000 !default;
-$gray-darker:            lighten($gray-base, 13.5%) !default; // #222
-$gray-dark:              lighten($gray-base, 20%) !default;   // #333
-$gray:                   lighten($gray-base, 33.5%) !default; // #555
-$gray-light:             lighten($gray-base, 70%) !default;   // #999
-$gray-lighter:           lighten($gray-base, 93.5%) !default; // #eee
-
-$gray-lightest:          lighten($gray-lighter, 13.5%);
-
-$brand-primary:         #4582EC !default;
-$brand-success:         #3FAD46 !default;
-$brand-info:            #5bc0de !default;
-$brand-warning:         #f0ad4e !default;
-$brand-danger:          #d9534f !default;
-
-
-//== Scaffolding
-//
-//## Settings for some of the most global styles.
-
-//** Background color for `<body>`.
-$body-bg:               #fff !default;
-//** Global text color on `<body>`.
-$text-color:            $gray-dark !default;
-
-$body-color: $text-color;
-
-//** Global textual link color.
-$link-color:            $brand-primary !default;
-//** Link hover color set via `darken()` function.
-$link-hover-color:      darken($link-color, 20%) !default;
-//** Link hover decoration.
-$link-hover-decoration: underline !default;
-
-
-//== Typography
-//
-//## Font, line-height, and color for body text, headings, and more.
-
-$font-family-sans-serif:  "Raleway", "Helvetica Neue", Helvetica, Arial, sans-serif !default;
-$font-family-serif:       Georgia, "Times New Roman", Times, serif !default;
-//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
-$font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace !default;
-$font-family-base:        $font-family-serif !default;
-
-$font-size-base:          16px !default;
-$font-size-root: $font-size-base;
-
-$font-size-lg:         ceil(($font-size-base * 1.25)) !default; // ~18px
-$font-size-sm:         ceil(($font-size-base * 0.85)) !default; // ~12px
-
-$font-size-h1:            floor(($font-size-base * 2.6)) !default; // ~36px
-$font-size-h2:            floor(($font-size-base * 2.15)) !default; // ~30px
-$font-size-h3:            ceil(($font-size-base * 1.7)) !default; // ~24px
-$font-size-h4:            ceil(($font-size-base * 1.25)) !default; // ~18px
-$font-size-h5:            $font-size-base !default;
-$font-size-h6:            ceil(($font-size-base * 0.85)) !default; // ~12px
-
-//** Unit-less `line-height` for use in components like buttons.
-$line-height-base:        1.428571429 !default; // 20/14
-//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
-$line-height-computed:    floor(($font-size-base * $line-height-base)) !default; // ~20px
-
-//** By default, this inherits from the `<body>`.
-$headings-font-family:    $font-family-sans-serif !default;
-$headings-font-weight:    bold !default;
-$headings-line-height:    1.1 !default;
-$headings-color:          inherit !default;
-
-
-//== Iconography
-//
-//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
-
-//** Load fonts from this directory.
-$icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/") !default;
-//** File name for all font files.
-$icon-font-name:          "glyphicons-halflings-regular" !default;
-//** Element ID within SVG icon file.
-$icon-font-svg-id:        "glyphicons_halflingsregular" !default;
-
-
-//== Components
-//
-//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
-
-$padding-base-y:     8px !default;
-$padding-base-x:   12px !default;
-
-$padding-lg-y:    14px !default;
-$padding-lg-x:  16px !default;
-
-$padding-sm-y:    5px !default;
-$padding-sm-x:  10px !default;
-
-$padding-xs-y:       1px !default;
-$padding-xs-x:     5px !default;
-
-$line-height-lg:         1.3333333 !default; // extra decimals for Win 8.1 Chrome
-$line-height-sm:         1.5 !default;
-
-$border-radius:        4px !default;
-$border-radius-lg:       6px !default;
-$border-radius-sm:       3px !default;
-
-//** Global color for active items (e.g., navs or dropdowns).
-$component-active-color:    #fff !default;
-//** Global background color for active items (e.g., navs or dropdowns).
-$component-active-bg:       $brand-primary !default;
-
-//** Width of the `border` for generating carets that indicate dropdowns.
-$caret-width-base:          4px !default;
-//** Carets increase slightly in size for lgr components.
-$caret-width-lg:         5px !default;
-
-
-//== Tables
-//
-//## Customizes the `.table` component with basic values, each used across all table variations.
-
-//** Padding for `<th>`s and `<td>`s.
-$table-cell-padding:            8px !default;
-//** Padding for cells in `.table-condensed`.
-$table-sm-cell-padding:  5px !default;
-
-//** Default background color used for all tables.
-$table-bg:                      transparent !default;
-//** Background color used for `.table-striped`.
-$table-bg-accent:               #f9f9f9 !default;
-//** Background color used for `.table-hover`.
-$table-bg-hover:                #f5f5f5 !default;
-$table-bg-active:               $table-bg-hover !default;
-
-//** Border color for table and cell borders.
-$table-border-color:            #ddd !default;
-
-
-//== Buttons
-//
-//## For each of Bootstrap's buttons, define text, background and border color.
-
-$btn-font-weight:                normal !default;
-
-$btn-default-color:              $text-color !default;
-$btn-default-bg:                 #fff !default;
-$btn-default-border:             #ddd !default;
-
-$btn-secondary-color: $btn-default-color;
-$btn-secondary-bg: $btn-default-bg;
-$btn-secondary-border: $btn-default-border;
-
-
-
-$btn-primary-color:              #fff !default;
-$btn-primary-bg:                 $brand-primary !default;
-$btn-primary-border:             $btn-primary-bg !default;
-
-$btn-success-color:              #fff !default;
-$btn-success-bg:                 $brand-success !default;
-$btn-success-border:             $btn-success-bg !default;
-
-$btn-info-color:                 #fff !default;
-$btn-info-bg:                    $brand-info !default;
-$btn-info-border:                $btn-info-bg !default;
-
-$btn-warning-color:              #fff !default;
-$btn-warning-bg:                 $brand-warning !default;
-$btn-warning-border:             $btn-warning-bg !default;
-
-$btn-danger-color:               #fff !default;
-$btn-danger-bg:                  $brand-danger !default;
-$btn-danger-border:              $btn-danger-bg !default;
-
-$btn-link-disabled-color:        $gray-light !default;
-
-// Allows for customizing button radius independently from global border radius
-$btn-border-radius:         $border-radius !default;
-$btn-border-radius-lg:        $border-radius-lg !default;
-$btn-border-radius-sm:        $border-radius-sm !default;
-
-
-//== Forms
-//
-//##
-
-//** `<input>` background color
-$input-bg:                       #fff !default;
-//** `<input disabled>` background color
-$input-bg-disabled:              $gray-lighter !default;
-
-//** Text color for `<input>`s
-$input-color:                    $text-color !default;
-//** `<input>` border color
-$input-border:                   #ddd !default;
-
-// TODO: Rename `$input-border-radius` to `$input-border-radius` in v4
-//** Default `.form-control` border radius
-// This has no effect on `<select>`s in some browsers, due to the limited stylability of `<select>`s in CSS.
-$input-border-color: $input-border;
-
-$input-border-radius:            $border-radius !default;
-//** Large `.form-control` border radius
-$input-border-radius-lg:      $border-radius-lg !default;
-//** Small `.form-control` border radius
-$input-border-radius-sm:      $border-radius-sm !default;
-
-//** Border color for inputs on focus
-$input-border-focus:             #66afe9 !default;
-
-//** Placeholder text color
-$input-color-placeholder:        $gray-light !default;
-
-//** Default `.form-control` height
-$input-height:              ($line-height-computed + ($padding-base-y * 2) + 2) !default;
-//** Large `.form-control` height
-$input-height-lg:             (ceil($font-size-lg * $line-height-lg) + ($padding-lg-y * 2) + 2) !default;
-//** Small `.form-control` height
-$input-height-sm:             (floor($font-size-sm * $line-height-sm) + ($padding-sm-y * 2) + 2) !default;
-
-//** `.form-group` margin
-$form-group-margin-bottom:       15px !default;
-
-$legend-color:                   $text-color !default;
-$legend-border-color:            #e5e5e5 !default;
-
-//** Background color for textual input addons
-$input-group-addon-bg:           $gray-lighter !default;
-//** Border color for textual input addons
-$input-group-addon-border-color: $input-border !default;
-
-//** Disabled cursor for form controls and buttons.
-$cursor-disabled:                not-allowed !default;
-
-
-//== Dropdowns
-//
-//## Dropdown menu container and contents.
-
-//** Background for the dropdown menu.
-$dropdown-bg:                    #fff !default;
-//** Dropdown menu `border-color`.
-$dropdown-border:                rgba(0,0,0,.15) !default;
-//** Dropdown menu `border-color` **for IE8**.
-$dropdown-fallback-border:       #ccc !default;
-//** Divider color for between dropdown items.
-$dropdown-divider-bg:            #e5e5e5 !default;
-
-//** Dropdown link text color.
-$dropdown-link-color:            $gray-dark !default;
-//** Hover color for dropdown links.
-$dropdown-link-hover-color:      #fff !default;
-//** Hover background for dropdown links.
-$dropdown-link-hover-bg:         $component-active-bg !default;
-
-//** Active dropdown menu item text color.
-$dropdown-link-active-color:     #fff !default;
-//** Active dropdown menu item background color.
-$dropdown-link-active-bg:        $component-active-bg !default;
-
-//** Disabled dropdown menu item background color.
-$dropdown-link-disabled-color:   $gray-light !default;
-
-//** Text color for headers within dropdown menus.
-$dropdown-header-color:          $gray-light !default;
-
-//** Deprecated `$dropdown-caret-color` as of v3.1.0
-$dropdown-caret-color:           #000 !default;
-
-
-//-- Z-index master list
-//
-// Warning: Avoid customizing these values. They're used for a bird's eye view
-// of components dependent on the z-axis and are designed to all work together.
-//
-// Note: These variables are not generated into the Customizer.
-
-$zindex-navbar:            1000 !default;
-$zindex-dropdown:          1000 !default;
-$zindex-popover:           1060 !default;
-$zindex-tooltip:           1070 !default;
-$zindex-navbar-fixed:      1030 !default;
-$zindex-modal-background:  1040 !default;
-$zindex-modal:             1050 !default;
-
-
-//== Media queries breakpoints
-//
-//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
-
-// Extra sm screen / phone
-//** Deprecated `$screen-xs` as of v3.0.1
-$screen-xs:                  480px !default;
-//** Deprecated `$screen-xs-min` as of v3.2.0
-$screen-xs-min:              $screen-xs !default;
-//** Deprecated `$screen-phone` as of v3.0.1
-$screen-phone:               $screen-xs-min !default;
-
-// Small screen / tablet
-//** Deprecated `$screen-sm` as of v3.0.1
-$screen-sm:                  768px !default;
-$screen-sm-min:              $screen-sm !default;
-//** Deprecated `$screen-tablet` as of v3.0.1
-$screen-tablet:              $screen-sm-min !default;
-
-// Medium screen / desktop
-//** Deprecated `$screen-md` as of v3.0.1
-$screen-md:                  992px !default;
-$screen-md-min:              $screen-md !default;
-//** Deprecated `$screen-desktop` as of v3.0.1
-$screen-desktop:             $screen-md-min !default;
-
-// Large screen / wide desktop
-//** Deprecated `$screen-lg` as of v3.0.1
-$screen-lg:                  1200px !default;
-$screen-lg-min:              $screen-lg !default;
-//** Deprecated `$screen-lg-desktop` as of v3.0.1
-$screen-lg-desktop:          $screen-lg-min !default;
-
-// So media queries don't overlap when required, provide a maximum
-$screen-xs-max:              ($screen-sm-min - 1) !default;
-$screen-sm-max:              ($screen-md-min - 1) !default;
-$screen-md-max:              ($screen-lg-min - 1) !default;
-
-
-//== Grid system
-//
-//## Define your custom responsive grid.
-
-//** Number of columns in the grid.
-$grid-columns:              12 !default;
-//** Padding between columns. Gets divided in half for the left and right.
-$grid-gutter-width:         30px !default;
-// Navbar collapse
-//** Point at which the navbar becomes uncollapsed.
-$grid-float-breakpoint:     $screen-sm-min !default;
-//** Point at which the navbar begins collapsing.
-$grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default;
-
-
-//== Container sizes
-//
-//## Define the maximum width of `.container` for different screen sizes.
-
-// Small screen / tablet
-$container-tablet:             (720px + $grid-gutter-width) !default;
-//** For `$screen-sm-min` and up.
-$container-sm:                 $container-tablet !default;
-
-// Medium screen / desktop
-$container-desktop:            (940px + $grid-gutter-width) !default;
-//** For `$screen-md-min` and up.
-$container-md:                 $container-desktop !default;
-
-// Large screen / wide desktop
-$container-lg-desktop:      (1140px + $grid-gutter-width) !default;
-//** For `$screen-lg-min` and up.
-$container-lg:                 $container-lg-desktop !default;
-
-
-//== Navbar
-//
-//##
-
-// Basics of a navbar
-$navbar-height:                    65px !default;
-$navbar-margin-bottom:             $line-height-computed !default;
-$navbar-border-radius:             $border-radius !default;
-$navbar-padding-x:        floor(($grid-gutter-width / 2)) !default;
-$navbar-padding-y:          (($navbar-height - $line-height-computed) / 2) !default;
-$navbar-collapse-max-height:       340px !default;
-
-$navbar-light-color:             $text-color !default;
-$navbar-light-bg:                $body-bg !default;
-$navbar-light-border:            #ddd !default;
-
-// Navbar links
-$navbar-light-link-color:                $link-color !default;
-$navbar-light-link-hover-color:          $link-color !default;
-$navbar-light-link-hover-bg:             transparent !default;
-$navbar-light-link-active-color:         $navbar-light-link-color !default;
-$navbar-light-link-active-bg:            transparent !default;
-$navbar-light-link-disabled-color:       #333 !default;
-$navbar-light-link-disabled-bg:          transparent !default;
-
-// Navbar brand label
-$navbar-light-brand-color:               $navbar-light-link-color !default;
-$navbar-light-brand-hover-color:         $navbar-light-link-hover-color !default;
-$navbar-light-brand-hover-bg:            transparent !default;
-
-// Navbar toggle
-$navbar-light-toggle-hover-bg:           #ddd !default;
-$navbar-light-toggle-icon-bar-bg:        #ccc !default;
-$navbar-light-toggle-border-color:       #ddd !default;
-
-
-//=== Inverted navbar
-// Reset inverted navbar basics
-$navbar-dark-color:                      $text-color !default;
-$navbar-dark-bg:                         $body-bg !default;
-$navbar-dark-border:                     #ddd !default;
-
-// Inverted navbar links
-$navbar-dark-link-color:                 $text-color !default;
-$navbar-dark-link-hover-color:           $text-color !default;
-$navbar-dark-link-hover-bg:              transparent !default;
-$navbar-dark-link-active-color:          $text-color !default;
-$navbar-dark-link-active-bg:             transparent !default;
-$navbar-dark-link-disabled-color:        #ccc !default;
-$navbar-dark-link-disabled-bg:           transparent !default;
-
-// Inverted navbar brand label
-$navbar-dark-brand-color:                $navbar-dark-link-color !default;
-$navbar-dark-brand-hover-color:          $navbar-dark-link-hover-color !default;
-$navbar-dark-brand-hover-bg:             transparent !default;
-
-// Inverted navbar toggle
-$navbar-dark-toggle-hover-bg:            #ddd !default;
-$navbar-dark-toggle-icon-bar-bg:         #ccc !default;
-$navbar-dark-toggle-border-color:        #ddd !default;
-
-
-//== Navs
-//
-//##
-
-//=== Shared nav styles
-$nav-link-padding:                          10px 15px !default;
-$nav-link-hover-bg:                         $gray-lighter !default;
-
-$nav-disabled-link-color:                   $gray-light !default;
-$nav-disabled-link-hover-color:             $gray-light !default;
-
-//== Tabs
-$nav-tabs-border-color:                     #ddd !default;
-
-$nav-tabs-link-hover-border-color:          $gray-lighter !default;
-
-$nav-tabs-active-link-hover-bg:             $body-bg !default;
-$nav-tabs-active-link-hover-color:          $gray !default;
-$nav-tabs-active-link-hover-border-color:   #ddd !default;
-
-$nav-tabs-justified-link-border-color:            #ddd !default;
-$nav-tabs-justified-active-link-border-color:     $body-bg !default;
-
-//== Pills
-$nav-pills-border-radius:                   $border-radius !default;
-$nav-pills-active-link-hover-bg:            $component-active-bg !default;
-$nav-pills-active-link-hover-color:         $component-active-color !default;
-
-
-//== Pagination
-//
-//##
-
-$pagination-color:                     $text-color !default;
-$pagination-bg:                        #fff !default;
-$pagination-border:                    #ddd !default;
-
-$pagination-border-color: $pagination-border;
-
-$pagination-hover-color:               #fff !default;
-$pagination-hover-bg:                  $brand-primary !default;
-$pagination-hover-border:              $brand-primary !default;
-
-$pagination-active-color:              #fff !default;
-$pagination-active-bg:                 $brand-primary !default;
-$pagination-active-border:             $brand-primary !default;
-
-$pagination-disabled-color:            $gray-light !default;
-$pagination-disabled-bg:               #fff !default;
-$pagination-disabled-border:           #ddd !default;
-
-
-//== Pager
-//
-//##
-
-$pager-bg:                             $pagination-bg !default;
-$pager-border:                         $pagination-border !default;
-$pager-border-radius:                  15px !default;
-
-$pager-hover-bg:                       $pagination-hover-bg !default;
-
-$pager-active-bg:                      $pagination-active-bg !default;
-$pager-active-color:                   $pagination-active-color !default;
-
-$pager-disabled-color:                 $gray-light !default;
-
-
-//== Jumbotron
-//
-//##
-
-$jumbotron-padding:              30px !default;
-$jumbotron-color:                inherit !default;
-$jumbotron-bg:                   darken($body-bg, 3%) !default;
-$jumbotron-heading-color:        inherit !default;
-$jumbotron-font-size:            ceil(($font-size-base * 1.5)) !default;
-$jumbotron-heading-font-size:    ceil(($font-size-base * 4.5)) !default;
-
-
-//== Form states and alerts
-//
-//## Define colors for form feedback states and, by default, alerts.
-
-$state-success-text:             $brand-success !default;
-$state-success-bg:               #dff0d8 !default;
-$state-success-border:           $brand-success !default;
-
-$state-info-text:                $brand-info !default;
-$state-info-bg:                  #d9edf7 !default;
-$state-info-border:              $brand-info !default;
-
-$state-warning-text:             $brand-warning !default;
-$state-warning-bg:               #fcf8e3 !default;
-$state-warning-border:           $brand-warning !default;
-
-$state-danger-text:              $brand-danger !default;
-$state-danger-bg:                #f2dede !default;
-$state-danger-border:            $brand-danger !default;
-
-
-//== Tooltips
-//
-//##
-
-//** Tooltip max width
-$tooltip-max-width:           200px !default;
-//** Tooltip text color
-$tooltip-color:               #fff !default;
-//** Tooltip background color
-$tooltip-bg:                  #000 !default;
-$tooltip-opacity:             .9 !default;
-
-//** Tooltip arrow width
-$tooltip-arrow-width:         5px !default;
-//** Tooltip arrow color
-$tooltip-arrow-color:         $tooltip-bg !default;
-
-
-//== Popovers
-//
-//##
-
-//** Popover body background color
-$popover-bg:                          #fff !default;
-//** Popover maximum width
-$popover-max-width:                   276px !default;
-//** Popover border color
-$popover-border-color:                rgba(0,0,0,.2) !default;
-//** Popover fallback border color
-$popover-fallback-border-color:       #ccc !default;
-
-//** Popover title background color
-$popover-title-bg:                    darken($popover-bg, 3%) !default;
-
-//** Popover arrow width
-$popover-arrow-width:                 10px !default;
-//** Popover arrow color
-$popover-arrow-color:                 $popover-bg !default;
-
-//** Popover outer arrow width
-$popover-arrow-outer-width:           ($popover-arrow-width + 1) !default;
-//** Popover outer arrow color
-$popover-arrow-outer-color:           fadein($popover-border-color, 5%) !default;
-//** Popover outer arrow fallback color
-$popover-arrow-outer-fallback-color:  darken($popover-fallback-border-color, 20%) !default;
-
-
-//== Labels
-//
-//##
-
-//** Default label background color
-$tag-default-bg:            $btn-default-bg !default;
-//** Primary label background color
-$tag-primary-bg:            $brand-primary !default;
-//** Success label background color
-$tag-success-bg:            $brand-success !default;
-//** Info label background color
-$tag-info-bg:               $brand-info !default;
-//** Warning label background color
-$tag-warning-bg:            $brand-warning !default;
-//** Danger label background color
-$tag-danger-bg:             $brand-danger !default;
-
-//** Default label text color
-$tag-color:                 #fff !default;
-//** Default text color of a linked label
-$tag-link-hover-color:      #fff !default;
-
-
-//== Modals
-//
-//##
-
-//** Padding applied to the modal body
-$modal-inner-padding:         20px !default;
-
-//** Padding applied to the modal title
-$modal-title-padding:         15px !default;
-//** Modal title line-height
-$modal-title-line-height:     $line-height-base !default;
-
-//** Background color of modal content area
-$modal-content-bg:                             #fff !default;
-//** Modal content border color
-$modal-content-border-color:                   rgba(0,0,0,.2) !default;
-//** Modal content border color **for IE8**
-$modal-content-fallback-border-color:          #999 !default;
-
-//** Modal backdrop background color
-$modal-backdrop-bg:           #000 !default;
-//** Modal backdrop opacity
-$modal-backdrop-opacity:      .5 !default;
-//** Modal header border color
-$modal-header-border-color:   #e5e5e5 !default;
-//** Modal footer border color
-$modal-footer-border-color:   $modal-header-border-color !default;
-
-$modal-lg:                    900px !default;
-$modal-md:                    600px !default;
-$modal-sm:                    300px !default;
-
-
-//== Alerts
-//
-//## Define alert colors, border radius, and padding.
-
-$alert-padding:               15px !default;
-$alert-border-radius:         $border-radius !default;
-$alert-link-font-weight:      bold !default;
-
-$alert-success-bg:            $state-success-border !default;
-$alert-success-text:          #fff !default;
-$alert-success-border:        $state-success-border !default;
-
-$alert-info-bg:               $state-info-border !default;
-$alert-info-text:             #fff !default;
-$alert-info-border:           $state-info-border !default;
-
-$alert-warning-bg:            $state-warning-border !default;
-$alert-warning-text:          #fff !default;
-$alert-warning-border:        $state-warning-border !default;
-
-$alert-danger-bg:             $state-danger-border !default;
-$alert-danger-text:           #fff !default;
-$alert-danger-border:         $state-danger-border !default;
-
-
-//== Progress bars
-//
-//##
-
-//** Background color of the whole progress component
-$progress-bg:                 #f5f5f5 !default;
-//** Progress bar text color
-$progress-bar-color:          #fff !default;
-//** Variable for setting rounded corners on progress bar.
-$progress-border-radius:      $border-radius !default;
-
-//** Default progress bar color
-$progress-bar-bg:             $brand-primary !default;
-//** Success progress bar color
-$progress-bar-success-bg:     $brand-success !default;
-//** Warning progress bar color
-$progress-bar-warning-bg:     $brand-warning !default;
-//** Danger progress bar color
-$progress-bar-danger-bg:      $brand-danger !default;
-//** Info progress bar color
-$progress-bar-info-bg:        $brand-info !default;
-
-
-//== List group
-//
-//##
-
-//** Background color on `.list-group-item`
-$list-group-bg:                 #fff !default;
-//** `.list-group-item` border color
-$list-group-border:             #ddd !default;
-//** List group border radius
-$list-group-border-radius:      $border-radius !default;
-
-//** Background color of single list items on hover
-$list-group-hover-bg:           #f5f5f5 !default;
-//** Text color of active list items
-$list-group-active-color:       $component-active-color !default;
-//** Background color of active list items
-$list-group-active-bg:          $component-active-bg !default;
-//** Border color of active list elements
-$list-group-active-border:      $list-group-active-bg !default;
-//** Text color for content within active list items
-$list-group-active-text-color:  lighten($list-group-active-bg, 40%) !default;
-
-//** Text color of disabled list items
-$list-group-disabled-color:      $gray-light !default;
-//** Background color of disabled list items
-$list-group-disabled-bg:         $gray-lighter !default;
-//** Text color for content within disabled list items
-$list-group-disabled-text-color: $list-group-disabled-color !default;
-
-$list-group-link-color:         #555 !default;
-$list-group-link-hover-color:   $list-group-link-color !default;
-$list-group-link-heading-color: #333 !default;
-
-
-//== Panels
-//
-//##
-
-$card-bg:                    #fff !default;
-$card-body-padding:          15px !default;
-$card-heading-padding:       10px 15px !default;
-$card-footer-padding:        $card-heading-padding !default;
-$card-border-radius:         $border-radius !default;
-
-//** Border color for elements within panels
-$card-inner-border:          #ddd !default;
-$card-footer-bg:             #fff !default;
-
-$card-default-text:          $gray-dark !default;
-$card-default-border:        #ddd !default;
-$card-default-heading-bg:    #f5f5f5 !default;
-
-$card-primary-text:          #fff !default;
-$card-primary-border:        $brand-primary !default;
-$card-primary-heading-bg:    $brand-primary !default;
-
-$card-success-text:          #fff !default;
-$card-success-border:        $state-success-border !default;
-$card-success-heading-bg:    $state-success-border !default;
-
-$card-info-text:             #fff !default;
-$card-info-border:           $state-info-border !default;
-$card-info-heading-bg:       $state-info-border !default;
-
-$card-warning-text:          #fff !default;
-$card-warning-border:        $state-warning-border !default;
-$card-warning-heading-bg:    $state-warning-border !default;
-
-$card-danger-text:           #fff !default;
-$card-danger-border:         $state-danger-border !default;
-$card-danger-heading-bg:     $state-danger-border !default;
-
-
-//== Thumbnails
-//
-//##
-
-//** Padding around the thumbnail image
-$thumbnail-padding:           4px !default;
-//** Thumbnail background color
-$thumbnail-bg:                $body-bg !default;
-//** Thumbnail border color
-$thumbnail-border:            #ddd !default;
-//** Thumbnail border radius
-$thumbnail-border-radius:     $border-radius !default;
-
-//** Custom text color for thumbnail captions
-$thumbnail-caption-color:     $text-color !default;
-//** Padding around the thumbnail caption
-$thumbnail-caption-padding:   9px !default;
-
-
-//== Wells
-//
-//##
-
-$well-bg:                     darken($body-bg, 3%) !default;
-$well-border:                 darken($well-bg, 7%) !default;
-
-
-//== Badges
-//
-//##
-
-$badge-color:                 #fff !default;
-//** Linked badge text color on hover
-$badge-link-hover-color:      #fff !default;
-$badge-bg:                    $brand-primary !default;
-
-//** Badge text color in active nav link
-$badge-active-color:          $link-color !default;
-//** Badge background color in active nav link
-$badge-active-bg:             #fff !default;
-
-$badge-font-weight:           bold !default;
-$badge-line-height:           1 !default;
-$badge-border-radius:         10px !default;
-
-
-//== Breadcrumbs
-//
-//##
-
-$breadcrumb-padding-y:   8px !default;
-$breadcrumb-padding-x: 15px !default;
-//** Breadcrumb background color
-$breadcrumb-bg:                 #f5f5f5 !default;
-//** Breadcrumb text color
-$breadcrumb-color:              #ccc !default;
-//** Text color of current page in the breadcrumb
-$breadcrumb-active-color:       $gray-light !default;
-//** Textual separator for between breadcrumb elements
-$breadcrumb-separator:          "/" !default;
-
-
-//== Carousel
-//
-//##
-
-$carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6) !default;
-
-$carousel-control-color:                      #fff !default;
-$carousel-control-width:                      15% !default;
-$carousel-control-opacity:                    .5 !default;
-$carousel-control-font-size:                  20px !default;
-
-$carousel-indicator-active-bg:                #fff !default;
-$carousel-indicator-border-color:             #fff !default;
-
-$carousel-caption-color:                      #fff !default;
-
-
-//== Close
-//
-//##
-
-$close-font-weight:           bold !default;
-$close-color:                 #fff !default;
-$close-text-shadow:           0 1px 0 #fff !default;
-
-
-//== Code
-//
-//##
-
-$code-color:                  #c7254e !default;
-$code-bg:                     #f9f2f4 !default;
-
-$kbd-color:                   #fff !default;
-$kbd-bg:                      #333 !default;
-
-$pre-bg:                      #f5f5f5 !default;
-$pre-color:                   $gray-dark !default;
-$pre-border-color:            #ccc !default;
-$pre-scrollable-max-height:   340px !default;
-
-
-//== Type
-//
-//##
-
-//** Horizontal offset for forms and lists.
-$component-offset-x: 180px !default;
-//** Text muted color
-$text-muted:                  $gray-light !default;
-//** Abbreviations and acronyms border color
-$abbr-border-color:           $gray-light !default;
-//** Headings sm color
-$headings-sm-color:        $gray-light !default;
-//** Blockquote sm color
-$blockquote-sm-color:      $text-color !default;
-//** Blockquote font size
-$blockquote-font-size:        ($font-size-base * 1.25) !default;
-//** Blockquote border color
-$blockquote-border-color:     $brand-primary !default;
-//** Page header border color
-$page-header-border-color:    #ddd !default;
-//** Width of x description list titles
-$dl-x-offset:        $component-offset-x !default;
-//** Point at which .dl-x becomes x
-$dl-x-breakpoint:    $grid-float-breakpoint !default;
-//** Horizontal line color.
-$hr-border:                   $gray-lighter !default;
-
-@import "moodle";
-
-@mixin placeholder($text) {
-    placeholder: $text;
-}
-@mixin box-shadow($text) {
-    box-shadow: $text;
-}
-@mixin transform($transforms) {
-    transform: $transforms;
-}
-@mixin rotate ($deg) {
-    @include transform(rotate(#{$deg}deg));
-}
-@mixin scale($scale) {
-    @include transform(scale($scale));
-}
-@mixin translate ($x, $y) {
-    @include transform(translate($x, $y));
-}
-@mixin skew ($x, $y) {
-    @include transform(skew(#{$x}deg, #{$y}deg));
-}
-@mixin transform-origin ($origin) {
-    transform-origin: $origin;
-}
-// Readable 3.3.7
-// Bootswatch
-// -----------------------------------------------------
-
-$web-font-path: "https://fonts.googleapis.com/css?family=Raleway:400,700" !default;
-@import url($web-font-path);
-
-// Navbar =====================================================================
-
-.navbar {
-  font-family: $headings-font-family;
-
-  &-nav,
-  &-form {
-    margin-left: 0;
-    margin-right: 0;
-  }
-
-  &-nav > li > a {
-    $margin-y: (($navbar-height - 2*$padding-base-y - $line-height-computed - 2px) / 2);
-    margin: $margin-y 6px;
-    padding: $padding-base-y $padding-base-x;
-    border: 1px solid transparent;
-    border-radius: $border-radius;
-
-    &:hover {
-      border: 1px solid #ddd;
-    }
-  }
-
-  &-nav > .active > a,
-  &-nav > .active > a:hover {
-    border: 1px solid #ddd;
-  }
-
-  &-default .navbar-nav > .active > a:hover {
-    color: $navbar-light-link-hover-color;
-  }
-
-  &-inverse .navbar-nav > .active > a:hover {
-    color: $navbar-dark-link-hover-color;
-  }
-
-  &-brand {
-    padding-top: (($navbar-height - 2*$font-size-lg) / 2);
-    padding-bottom: (($navbar-height - 2*$font-size-lg) / 2);
-    line-height: 1.9;
-  }
-}
-
-@media (min-width: $grid-float-breakpoint) {
-  .navbar {
-    .navbar-nav > li > a {
-      padding: $padding-base-y $padding-base-x;
-    }
-  }
-}
-
-@media (max-width: ($grid-float-breakpoint - 1)) {
-  .navbar {
-    .navbar-nav > li > a {
-      margin: 0;
-    }
-  }
-}
-
-// Buttons ====================================================================
-
-.btn {
-  font-family: $headings-font-family;
-}
-
-// Typography =================================================================
-
-// Tables =====================================================================
-
-// Forms ======================================================================
-
-legend {
-  font-family: $headings-font-family;
-}
-
-.input-group-addon {
-  font-family: $font-family-sans-serif;
-}
-
-// Navs =======================================================================
-
-.nav {
-  .open > a,
-  .open > a:hover,
-  .open > a:focus {
-    border: 1px solid #ddd;
-  }
-}
-
-.pagination {
-
-  font-family: $headings-font-family;
-
-  &-lg > li > a,
-  &-lg > li > span {
-    padding: 14px 24px;
-  }
-}
-
-.pager {
-
-  font-family: $headings-font-family;
-
-  a {
-    color: $text-color;
-  }
-
-  a:hover {
-    border-color: transparent;
-    color: #fff;
-  }
-
-  .disabled a {
-    border-color: $pager-border;
-  }
-}
-
-// Indicators =================================================================
-
-.close {
-  color: #fff;
-  text-decoration: none;
-  text-shadow: none;
-  opacity: 0.4;
-
-  &:hover,
-  &:focus {
-    color: #fff;
-    opacity: 1;
-  }
-}
-
-.alert {
-  .alert-link {
-    color: $alert-success-text;
-    text-decoration: underline;
-  }
-}
-
-.label {
-  font-family: $headings-font-family;
-  font-weight: normal;
-
-  &-default {
-    border: 1px solid #ddd;
-    color: $text-color;
-  }
-
-}
-
-.badge {
-  padding: 1px 7px 5px;
-  y-align: 2px;
-  font-family: $headings-font-family;
-  font-weight: normal;
-}
-
-// Progress bars ==============================================================
-
-// Containers =================================================================
-
-.panel {
-  @include box-shadow(none);
-
-  &-default {
-    .close {
-      color: $text-color;
-    }
-  }
-}
-
-.modal {
-  .close {
-    color: $text-color;
-  }
-}
diff --git a/theme/boost/scss/preset.scss b/theme/boost/scss/preset.scss
new file mode 100644 (file)
index 0000000..fcbabe1
--- /dev/null
@@ -0,0 +1 @@
+// This file is intentionally empty.
index 505db9b..326c205 100644 (file)
@@ -30,19 +30,33 @@ if ($ADMIN->fulltree) {
     $name = 'theme_boost/preset';
     $title = get_string('preset', 'theme_boost');
     $description = get_string('preset_desc', 'theme_boost');
-    $choices = [
-        // A file named 'preset-' . key . '.scss' is expected.
-        'plain' => get_string('presetplain', 'theme_boost'),
-        'default' => get_string('presetdefault', 'theme_boost'),
-        'flatly' => get_string('presetflatly', 'theme_boost'),
-        'paper' => get_string('presetpaper', 'theme_boost'),
-        'readable' => get_string('presetreadable', 'theme_boost')
-    ];
-    $default = 'default';
+    $default = 'default.scss';
+
+    $context = context_system::instance();
+    $fs = get_file_storage();
+    $files = $fs->get_area_files($context->id, 'theme_boost', 'preset', 0, 'itemid, filepath, filename', false);
+
+    $choices = [];
+    foreach ($files as $file) {
+        $choices[$file->get_filename()] = $file->get_filename();
+    }
+    // These are the built in presets.
+    $choices['default.scss'] = 'default.scss';
+    $choices['plain.scss'] = 'plain.scss';
+
     $setting = new admin_setting_configselect($name, $title, $description, $default, $choices);
     $setting->set_updatedcallback('theme_reset_all_caches');
     $page->add($setting);
 
+    // Preset files setting.
+    $name = 'theme_boost/presetfiles';
+    $title = get_string('presetfiles','theme_boost');
+    $description = get_string('presetfiles_desc', 'theme_boost');
+
+    $setting = new admin_setting_configstoredfile($name, $title, $description, 'preset', 0,
+        array('maxfiles' => 20, 'accepted_types' => array('.scss')));
+    $page->add($setting);
+
     // Variable $body-color.
     // We use an empty default value because the default colour should come from the preset.
     $name = 'theme_boost/brandcolor';
index 6f0f930..b50856b 100644 (file)
     <div id="page" class="container-fluid">
         <div id="page-content" class="row">
             <div id="region-main-box" class="col-xs-12">
+                <div id="region-main-settings-menu">
+                    <div> {{{ output.region_main_settings_menu }}} </div>
+                </div>
                 <section id="region-main">
                     <div class="card card-block">
-                    <span class="pull-xs-right region-main-settings-menu">
-                        {{{ output.region_main_settings_menu }}}
-                    </span>
                     {{{ output.course_content_header }}}
                     {{{ output.main_content }}}
                     {{{ output.course_content_footer }}}
index 413431c..2c0a0d0 100644 (file)
                 <section data-region="blocks-column" class="hidden-md-down">
                     {{{ sidepreblocks }}}
                 </section>
+                <div id="region-main-settings-menu" class="has-blocks">
+                    <div> {{{ output.region_main_settings_menu }}} </div>
+                </div>
                 <section id="region-main" class="has-blocks">
                 {{/hasblocks}}
                 {{^hasblocks}}
+                <div id="region-main-settings-menu">
+                    <div> {{{ output.region_main_settings_menu }}} </div>
+                </div>
                 <section id="region-main">
                 {{/hasblocks}}
                     <div class="card card-block">
-                    <span class="pull-xs-right region-main-settings-menu">
-                        {{{ output.region_main_settings_menu }}}
-                    </span>
                     {{{ output.course_content_header }}}
                     {{{ output.main_content }}}
                     {{{ output.course_content_footer }}}
index d1e33a4..5abbe5b 100644 (file)
@@ -1,6 +1,6 @@
-<button class="btn btn-link p-a-0" type="button"
+<a class="btn btn-link p-a-0" role="button"
     data-container="body" data-toggle="popover"
     data-placement="{{#ltr}}right{{/ltr}}{{^ltr}}left{{/ltr}}" data-content="{{text}} {{completedoclink}}"
-    data-html="true" tabindex="0" data-trigger="click">
+    data-html="true" tabindex="0" data-trigger="focus">
   {{#pix}}help, core, {{alt}}{{/pix}}
-</button>
\ No newline at end of file
+</a>
index d532554..257e81f 100644 (file)
 }}
 <div class="form-password">
     <span data-passwordunmask="wrapper" data-passwordunmaskid="{{ id }}">
-        <noscript>
-            <!-- Backwards compatability for Behat -->
-            <input  type="password"
-                    name="{{ name }}"
-                    id="{{ id }}"
-                    value="{{ value }}"
-                    size="{{ size }}"
-                    class="form-control d-inline-block"
-                    >
-        </noscript>
         <span class="visibleifjs">
             <span data-passwordunmask="editor">
-                <!-- The input in the noscript will be moved here as part of the page load -->
+                <input  type="hidden"
+                        name="{{ name }}"
+                        id="{{ id }}"
+                        value="{{ value }}"
+                        size="{{ size }}"
+                        class="form-control d-inline-block"
+                        >
             </span>
             <a href="#" data-passwordunmask="edit" title="{{ edithint }}">
                 <span data-passwordunmask="displayvalue">{{> core_form/element-passwordunmask-fill }}</span>
                 {{# str }} passwordunmaskinstructions, form {{/ str }}
             </span>
         </span>
+        <noscript>
+            <!-- Backwards compatability for Behat -->
+            <input  type="password"
+                    name="{{ name }}"
+                    id="{{ id }}"
+                    value="{{ value }}"
+                    size="{{ size }}"
+                    class="form-control d-inline-block"
+                    >
+        </noscript>
     </span>
 </div>
 {{#js}}
index 476a567..3b11eb2 100644 (file)
@@ -21,8 +21,8 @@
         disabled
     {{/element.frozen}}
     {{{element.attributes}}} >
-    {{{label}}} {{{helpbutton}}}
-</label>
+    {{{label}}}
+</label> {{{helpbutton}}}
 <span class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
     {{{error}}}
 </span>
index 91de688..4098526 100644 (file)
@@ -22,8 +22,8 @@
                 disabled
             {{/element.frozen}}
             {{{element.attributes}}} >
-            {{{label}}} {{{helpbutton}}}
-        </label>
+            {{{label}}}
+        </label> {{{helpbutton}}}
         <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
             {{{error}}}
         </div>
index 2f7bd86..8249a9b 100644 (file)
@@ -24,8 +24,8 @@
         disabled
     {{/element.frozen}}
     {{{element.attributes}}} >
-    {{{label}}} {{{helpbutton}}}
-</label>
+    {{{label}}}
+</label> {{{helpbutton}}}
 <span class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
     {{{error}}}
 </span>
index 489e506..e0d0850 100644 (file)
                 disabled
             {{/element.frozen}}
             {{{element.attributes}}} >
-            {{{label}}} {{{helpbutton}}}
-        </label>
+            {{{label}}}
+        </label> {{{helpbutton}}}
         <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
             {{{error}}}
         </div>
     </div>
 </div>
+{{^element.frozen}}
 {{#js}}
 require(['theme_boost/form-display-errors'], function(module) {
     module.enhance({{#quote}}{{element.id}}{{/quote}});
index fd8ab56..a05945e 100644 (file)
@@ -21,8 +21,8 @@
     {{/error}}
     {{{element.attributes}}} >
 {{/element.frozen}}
-    {{{label}}} {{{helpbutton}}}
-</label>
+    {{{label}}}
+</label> {{{helpbutton}}}
 <span class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
     {{{error}}}
 </span>
index a052aaa..c16be99 100644 (file)
@@ -22,8 +22,8 @@
                 autofocus aria-describedby="id_error_{{element.name}}"
             {{/error}} {{{element.attributes}}} >
         {{/element.frozen}}
-            {{{label}}} {{{helpbutton}}}
-        </label>
+            {{{label}}}
+        </label> {{{helpbutton}}}
         <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
             {{{error}}}
         </div>
index 155f101..e865d88 100644 (file)
@@ -7,9 +7,9 @@
         {{#error}}
             autofocus aria-describedby="id_error_{{element.name}}"
         {{/error}}
-        {{element.attributes}} >
+        {{{element.attributes}}} >
         {{#element.options}}
-        <option value="{{value}}" {{#selected}}selected{{/selected}}>{{text}}</option>
+        <option value="{{value}}" {{#selected}}selected{{/selected}} {{#disabled}}disabled{{/disabled}} {{{optionattributes}}}>{{text}}</option>
         {{/element.options}}
     </select>
         {{/element.frozen}}
index 4ac6560..f36d60f 100644 (file)
@@ -7,9 +7,9 @@
             {{#error}}
                 autofocus aria-describedby="id_error_{{element.name}}"
             {{/error}}
-            {{element.attributes}} >
+            {{{element.attributes}}} >
             {{#element.options}}
-            <option value="{{value}}" {{#selected}}selected{{/selected}}>{{text}}</option>
+            <option value="{{value}}" {{#selected}}selected{{/selected}} {{#disabled}}disabled{{/disabled}} {{{optionattributes}}}>{{text}}</option>
             {{/element.options}}
         </select>
         {{/element.frozen}}
index 3889a87..72e767a 100644 (file)
@@ -13,7 +13,7 @@
         <optgroup label="{{text}}">
         {{/text}}
         {{#options}}
-        <option value="{{value}}" {{#selected}}selected{{/selected}}>{{{text}}}</option>
+        <option value="{{value}}" {{#selected}}selected{{/selected}} {{#disabled}}disabled{{/disabled}} {{{optionattributes}}}>{{{text}}}</option>
         {{/options}}
         {{#text}}
         </optgroup>
index 99b93e2..88fef74 100644 (file)
@@ -13,7 +13,7 @@
             <optgroup label="{{text}}">
             {{/text}}
             {{#options}}
-            <option value="{{value}}" {{#selected}}selected{{/selected}}>{{{text}}}</option>
+            <option value="{{value}}" {{#selected}}selected{{/selected}} {{#disabled}}disabled{{/disabled}} {{{optionattributes}}}>{{{text}}}</option>
             {{/options}}
             {{/element.optiongroups}}
             {{#text}}
index f561e5a..7b13c22 100644 (file)
@@ -7,9 +7,9 @@
             {{#error}}
                 autofocus aria-describedby="id_error_{{element.name}}"
             {{/error}}
-            {{element.attributes}} >
+            {{{element.attributes}}} >
             {{#element.options}}
-            <option value="{{value}}" {{#selected}}selected{{/selected}}>{{text}}</option>
+            <option value="{{value}}" {{#selected}}selected{{/selected}} {{#disabled}}disabled{{/disabled}} {{{optionattributes}}}>{{text}}</option>
             {{/element.options}}
         </select>
         {{/element.frozen}}
index a3a56fe..39fcaaf 100644 (file)
@@ -13,7 +13,7 @@
 
     {{{ output.standard_top_of_body_html }}}
 
-    <div id="page" class="container">
+    <div id="page" class="container card">
 
         <div class="row">
             <div class="col-xs-12 p-y-1">
         </div>
 
         <div id="page-content" class="row">
-            <div id="region-main-box" class="col-xs-12">
-                <div class="row">
-                    <section id="region-main" class="col-xs-12">
-                        {{{ output.main_content }}}
-                    </section>
-                </div>
-            </div>
+            <section id="region-main" class="col-xs-12">
+                {{{ output.main_content }}}
+            </section>
         </div>
 
     </div>
index 544a141..4c53f53 100644 (file)
     <version>1.3.3</version>
     <licenseversion></licenseversion>
   </library>
-  <library>
-    <location>scss/preset-flatly.scss</location>
-    <name>Flatly Bootswatch</name>
-    <license>(MIT)</license>
-    <version>3.3.7</version>
-    <licenseversion></licenseversion>
-  </library>
-  <library>
-    <location>scss/preset-paper.scss</location>
-    <name>Paper Bootswatch</name>
-    <license>(MIT)</license>
-    <version>3.3.7</version>
-    <licenseversion></licenseversion>
-  </library>
-  <library>
-    <location>scss/preset-readable.scss</location>
-    <name>Readable Bootswatch</name>
-    <license>(MIT)</license>
-    <version>3.3.7</version>
-    <licenseversion></licenseversion>
-  </library>
 </libraries>
index fcf0a74..732cfb2 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016071101;
+$plugin->version   = 2016102100;
 $plugin->requires  = 2016070700;
 $plugin->component = 'theme_boost';
index e503cb6..5ccdc4e 100644 (file)
 
 defined('MOODLE_INTERNAL') || die();
 
-$version  = 2016102100.01;              // YYYYMMDD      = weekly release date of this DEV branch.
+$version  = 2016102700.01;              // YYYYMMDD      = weekly release date of this DEV branch.
                                         //         RR    = release increments - 00 in DEV branches.
                                         //           .XX = incremental changes.
 
-$release  = '3.2dev (Build: 20161020)'; // Human-friendly version name
+$release  = '3.2dev (Build: 20161027)'; // Human-friendly version name
 
 $branch   = '32';                       // This version's branch.
 $maturity = MATURITY_ALPHA;             // This version's maturity level.