MDL-58428 renderer: Move renderer override from core
authorMathew May <mathewm@hotmail.co.nz>
Wed, 13 Feb 2019 08:29:22 +0000 (16:29 +0800)
committerSara Arjona <sara@moodle.com>
Tue, 26 Feb 2019 11:56:14 +0000 (12:56 +0100)
Also update all html_writer user to escape the namespace.
Also update the xpaths in behat

27 files changed:
admin/templates/setting.mustache
admin/templates/setting_configcolourpicker.mustache
admin/templates/setting_configduration.mustache
admin/templates/setting_configfile.mustache
admin/templates/setting_configmultiselect.mustache
admin/templates/setting_configmultiselect_optgroup.mustache
admin/templates/setting_configselect.mustache
admin/templates/setting_configselect_optgroup.mustache
admin/templates/setting_configtext.mustache
admin/templates/setting_configtextarea.mustache
admin/templates/setting_configtime.mustache
admin/templates/setting_courselist_frontpage.mustache
admin/templates/setting_devicedetectregex.mustache
admin/templates/setting_emoticons.mustache
admin/templates/setting_gradecat_combo.mustache
admin/templates/settings.mustache
lib/outputrenderers.php
theme/boost/classes/output/core_renderer.php
theme/bootstrapbase/classes/output/block_settings_renderer.php
theme/bootstrapbase/classes/output/core/course_renderer.php
theme/bootstrapbase/classes/output/core/files_renderer.php
theme/bootstrapbase/classes/output/core_course/management/renderer.php
theme/bootstrapbase/classes/output/core_renderer.php [new file with mode: 0644]
theme/bootstrapbase/renderers.php
theme/bootstrapbase/renderers/core_renderer.php
theme/bootstrapbase/tests/behat/behat_theme_bootstrapbase_behat_course.php
theme/bootstrapbase/tests/behat/behat_theme_bootstrapbase_behat_navigation.php

index ed17246..9881bbc 100644 (file)
 
     You should have received a copy of the GNU General Public License
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+}}{{!
+    @template core_admin/setting
+
+    Admin setting template.
+
+    Context variables required for this template:
+    * labelfor - id of the form element
+    * title - Setting title
+    * override - Overridden message
+    * warning - Warning message
+    * name - Setting name
+    * error - Error message
+    * element - The Element HTML
+    * forceltr - Force this element to be displayed LTR
+    * default - Default value
+
+    Example context (json):
+    {
+        "title": "Setting title",
+        "labelfor": "id0",
+        "override": "Overidden",
+        "warning": "Warning",
+        "name": "Name",
+        "error": "Error",
+        "element": "Raw HTML",
+        "forceltr": false,
+        "default": "Default value"
+    }
 }}
 {{!
     @template core_admin/setting
index eb8c487..c1503f8 100644 (file)
 
     You should have received a copy of the GNU General Public License
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+}}{{!
+    @template core_admin/setting_configcolourpicker
+
+    Admin setting colour picker template.
+
+    Context variables required for this template:
+    * icon - optional icon context (see pix_icon)
+    * name - element name
+    * id - element id
+    * value - element value
+    * haspreviewconfig - show preview of selected color
+
+    Example context (json):
+    {
+        "icon": false,
+        "name": "name0",
+        "id": "id0",
+        "value": "#555655",
+        "haspreviewconfig": false
+    }
 }}
 {{!
     @template core_admin/setting_configcolourpicker
index 3bad98c..bc66bbe 100644 (file)
 
     You should have received a copy of the GNU General Public License
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+}}{{!
+    @template core_admin/setting_configduration
+
+    Admin duration setting template.
+
+    Context variables required for this template:
+    * name - form element name
+    * options - list of options for units containing name, value, selected
+    * value - yes
+    * id - element id
+
+    Example context (json):
+    {
+        "name": "test",
+        "value": "5",
+        "id": "test0",
+        "options": [ { "name": "Minutes", "value": "mins", "selected": true } ]
+    }
 }}
 {{!
     @template core_admin/setting_configduration
index f249fe6..b7d71cb 100644 (file)
 
     You should have received a copy of the GNU General Public License
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+}}{{!
+    @template core_admin/setting_configfile
+
+    Admin file setting template.
+
+    Context variables required for this template:
+    * name - form element name
+    * id - element id
+    * size - size of the field
+    * readonly - Make the field readonly
+    * value - value
+    * showvalidity - Show a green check if the path is readable
+    * valid - True if the path is readable
+
+    Example context (json):
+    {
+        "name": "test",
+        "value": "/my-super-secret-path/file",
+        "id": "test0",
+        "readonly": true,
+        "showvalidity": true,
+        "valid": false
+    }
 }}
 {{!
     @template core_admin/setting_configfile
index 7465a7b..ce866e9 100644 (file)
 
     You should have received a copy of the GNU General Public License
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+}}{{!
+    @template core_admin/setting_configmultiselect
+
+    Admin multiselect setting template.
+
+    Context variables required for this template:
+    * name - form element name
+    * id - element id
+    * size - element size
+    * options - list of options containing name, value, selected
+
+    Example context (json):
+    {
+        "name": "test",
+        "id": "test0",
+        "size": "3",
+        "options": [ { "name": "Option 1", "value": "V", "selected": true },
+                     { "name": "Option 2", "value": "V", "selected": true } ]
+    }
 }}
 {{!
     @template core_admin/setting_configmultiselect
index 9fa61c5..cff46fd 100644 (file)
 
     You should have received a copy of the GNU General Public License
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+}}{{!
+    @template core_admin/setting_configmultiselect_optgroup
+
+    Admin multiselect setting template with optgroup support.
+
+    Context variables required for this template:
+    * name - form element name
+    * id - element id
+    * size - element size
+    * options - list of options not grouped
+    * optgroups - list of options grouped containing the group label and for each option: name, value, selected
+
+    Example context (json):
+    {
+        "name": "test",
+        "id": "test0",
+        "size": "3",
+        "options": [
+            { "name": "Option 1", "value": "V", "selected": false },
+            { "name": "Option 2", "value": "V", "selected": true }
+        ],
+        "optgroups": [
+            {
+                "label": "Group 1",
+                "options": [
+                    { "name": "Option 3", "value": "V", "selected": false },
+                    { "name": "Option 4", "value": "V", "selected": true }
+                ]
+            },
+            {
+                "label": "Group 2",
+                "options": [
+                    { "name": "Option 5", "value": "V", "selected": false },
+                    { "name": "Option 6", "value": "V", "selected": true }
+                ]
+            }
+        ]
+    }
 }}
 {{!
     @template core_admin/setting_configmultiselect_optgroup
index a90c260..18e9213 100644 (file)
 
     You should have received a copy of the GNU General Public License
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+}}{{!
+    @template core_admin/setting_configselect
+
+    Admin select setting template.
+
+    Context variables required for this template:
+    * name - form element name
+    * id - element id
+    * options - list of options containing name, value, selected
+
+    Example context (json):
+    {
+        "name": "test",
+        "id": "test0",
+        "options": [
+            { "name": "Option 1", "value": "V", "selected": true },
+            { "name": "Option 2", "value": "V", "selected": true }
+        ]
+    }
 }}
 {{!
     @template core_admin/setting_configselect
index ea5da12..aeb794b 100644 (file)
 
     You should have received a copy of the GNU General Public License
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+}}{{!
+    @template core_admin/setting_configselect_optgroup
+
+    Admin select with optgroup setting template.
+
+    Context variables required for this template:
+    * name - form element name
+    * id - element id
+    * options - list of options (not grouped)
+    * optgroups - list of options grouped containing the group label and for each option: name, value, selected
+
+    Example context (json):
+    {
+        "name": "test",
+        "id": "test0",
+        "options": [
+            { "name": "Option 1", "value": "V", "selected": false },
+            { "name": "Option 2", "value": "V", "selected": false }
+        ],
+        "optgroups": [
+            {
+                "label": "Group 1",
+                "options": [
+                    { "name": "Option 3", "value": "V", "selected": true },
+                    { "name": "Option 4", "value": "V", "selected": false }
+                ]
+            },
+            {
+                "label": "Group 2",
+                "options": [
+                    { "name": "Option 5", "value": "V", "selected": false },
+                    { "name": "Option 6", "value": "V", "selected": false }
+                ]
+            }
+        ]
+    }
 }}
 {{!
     @template core_admin/setting_configselect_optgroup
index 236228a..b41893c 100644 (file)
 
     You should have received a copy of the GNU General Public License
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+}}{{!
+    @template core_admin/setting_configtext
+
+    Admin text setting template.
+
+    Context variables required for this template:
+    * name - form element name
+    * id - element id
+    * value - element value
+    * size - element size
+    * forceltr - always display as ltr
+    * attributes - list of additional attributes containing name, value
+
+    Example context (json):
+    {
+        "name": "test",
+        "id": "test0",
+        "value": "A tall, dark stranger will have more fun than you.",
+        "size": "21",
+        "forceltr": false,
+        "attributes": [ { "name": "readonly", "value": "readonly" } ]
+    }
 }}
 {{!
     @template core_admin/setting_configtext
index ec6ded3..1eee2ff 100644 (file)
 
     You should have received a copy of the GNU General Public License
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+}}{{!
+    @template core_admin/setting_configtextarea
+
+    Admin textarea setting template.
+
+    Context variables required for this template:
+    * name - form element name
+    * id - element id
+    * rows - number of rows
+    * cols - number of cols
+    * value - default value
+    * forceltr - always display as ltr
+
+    Example context (json):
+    {
+        "name": "test",
+        "cols": "30",
+        "rows": "3",
+        "value": "Excellent day for putting Slinkies on an escalator.",
+        "id": "test0"
+    }
 }}
 {{!
     @template core_admin/setting_configtextarea
index b86b691..69c5a79 100644 (file)
 
     You should have received a copy of the GNU General Public License
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+}}{{!
+    @template core_admin/setting_configtime
+
+    Admin time setting template.
+
+    Context variables required for this template:
+    * name - form element name
+    * id - element id
+    * hours - list of valid hour options containing name, value, selected
+    * minutes - list of valid minute options containing name, value, selected
+
+    Example context (json):
+    {
+        "name": "test",
+        "id": "test0",
+        "minutes": [
+            { "name": "00", "value": "0", "selected": true },
+            { "name": "01", "value": "1", "selected": false }
+        ],
+        "hours": [
+            { "name": "1", "value": "1", "selected": true },
+            { "name": "2", "value": "2", "selected": false }
+        ]
+    }
 }}
 {{!
     @template core_admin/setting_configtime
index 2fe18cc..3a36030 100644 (file)
 
     You should have received a copy of the GNU General Public License
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+}}{{!
+    @template core_admin/setting_courselist_frontpage
+
+    Admin courselist_frontpage setting template.
+
+    Context variables required for this template:
+    * selects list of select objects containing id, name, key and options.
+      options is another nested list of items containing name, value and selected
+
+    Example context (json):
+    {
+        "selects": [
+            {
+                "id": "i1",
+                "name": "s1",
+                "key": "k1",
+                "options": [
+                    { "name": "Fish", "value": "snapper", "selected": true }
+                ]
+            }
+        ]
+    }
 }}
 {{!
     @template core_admin/setting_courselist_frontpage
index cc88862..e4bea23 100644 (file)
 
     You should have received a copy of the GNU General Public License
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+}}{{!
+    @template core_admin/setting_devicedetectregex
+
+    Admin devicedetectregex setting template.
+
+    Context variables required for this template:
+    * expressions - List of expressions containing index, name, expression and value
+
+    Example context (json):
+    {
+        "expressions": [
+            { "index": "i1", "name": "Name", "expression": "/bird|yellow/", "value": "Canary" }
+        ]
+    }
 }}
 {{!
     @template core_admin/setting_devicedetectregex
index 4c36174..072e1a7 100644 (file)
 
     You should have received a copy of the GNU General Public License
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+}}{{!
+    @template core_admin/setting_emoticons
+
+    Admin emoticons setting template.
+
+    Context variables required for this template:
+    * name - form element name
+    * id - element id
+
+    Example context (json):
+    {
+        "emoticons": [
+            { "fields": [
+                { "name": "Smile", "field": "f1", "value": ":)" }
+            ]}
+        ]
+    }
 }}
 {{!
     @template core_admin/setting_emoticons
index d64d75f..d2ab931 100644 (file)
 
     You should have received a copy of the GNU General Public License
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+}}{{!
+    @template core_admin/setting_gradecat_combo
+
+    Admin gradecat_combo setting template.
+
+    Context variables required for this template:
+    * name - form element name
+    * id - element id
+    * options - list of options containing name, value and selected
+    * forced - is it forced
+    * advanced - is it advanced
+
+    Example context (json):
+    {
+        "name": "test",
+        "id": "test0",
+        "options": [
+            { "name": "Option name", "value": "Value", "selected": true }
+        ],
+        "forced": true,
+        "advanced": true
+    }
 }}
 {{!
     @template core_admin/setting_gradecat_combo
index 0097305..b8694e8 100644 (file)
 
     You should have received a copy of the GNU General Public License
     along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+}}{{!
+    @template core_admin/settings
+
+    Admin settings form template.
+
+    Context variables required for this template:
+    * actionurl - url to submit to
+    * params - list of parameters containing name and value
+    * return - page to return to
+    * title - form title
+    * settings - raw html for settings
+    * showsave - true if we need save buttons
+
+    Example context (json):
+    {
+        "actionurl": "/",
+        "return": "/",
+        "title": "Settings Form",
+        "settings": "RAW HTML",
+        "showsave": true
+    }
 }}
 {{!
     @template core_admin/settings
index 4831e91..c4e5da5 100644 (file)
@@ -368,6 +368,38 @@ class renderer_base {
             theme_get_revision(), $logo);
     }
 
+    /**
+     * Whether we should display the logo in the navbar.
+     *
+     * We will when there are no main logos, and we have compact logo.
+     *
+     * @return bool
+     */
+    public function should_display_navbar_logo() {
+        $logo = $this->get_compact_logo_url();
+        return !empty($logo) && !$this->should_display_main_logo();
+    }
+
+    /**
+     * Whether we should display the main logo.
+     *
+     * @param int $headinglevel
+     * @return bool
+     */
+    public function should_display_main_logo($headinglevel = 1) {
+        global $PAGE;
+
+        // Only render the logo if we're on the front page or login page and the we have a logo.
+        $logo = $this->get_logo_url();
+        if ($headinglevel == 1 && !empty($logo)) {
+            if ($PAGE->pagelayout == 'frontpage' || $PAGE->pagelayout == 'login') {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
 }
 
 
@@ -512,6 +544,9 @@ class core_renderer extends renderer_base {
      */
     protected $unique_main_content_token;
 
+    /** @var custom_menu_item language The language menu if created */
+    protected $language = null;
+
     /**
      * Constructor
      *
@@ -593,7 +628,7 @@ class core_renderer extends renderer_base {
      * @return string HTML fragment.
      */
     public function standard_head_html() {
-        global $CFG, $SESSION;
+        global $CFG, $SESSION, $SITE, $PAGE;
 
         // Before we output any content, we need to ensure that certain
         // page components are set up.
@@ -689,6 +724,13 @@ class core_renderer extends renderer_base {
             $output .= "\n".$CFG->additionalhtmlhead;
         }
 
+        if ($PAGE->pagelayout == 'frontpage') {
+            $summary = s(strip_tags(format_text($SITE->summary, FORMAT_HTML)));
+            if (!empty($summary)) {
+                $output .= "<meta name=\"description\" content=\"$summary\" />\n";
+            }
+        }
+
         return $output;
     }
 
@@ -1591,15 +1633,23 @@ class core_renderer extends renderer_base {
     /**
      * Renders an action menu component.
      *
-     * ARIA references:
-     *   - http://www.w3.org/WAI/GL/wiki/Using_ARIA_menus
-     *   - http://stackoverflow.com/questions/12279113/recommended-wai-aria-implementation-for-navigation-bar-menu
-     *
      * @param action_menu $menu
      * @return string HTML
      */
     public function render_action_menu(action_menu $menu) {
+
+        // We don't want the class icon there!
+        foreach ($menu->get_secondary_actions() as $action) {
+            if ($action instanceof \action_menu_link && $action->has_class('icon')) {
+                $action->attributes['class'] = preg_replace('/(^|\s+)icon(\s+|$)/i', '', $action->attributes['class']);
+            }
+        }
+
+        if ($menu->is_empty()) {
+            return '';
+        }
         $context = $menu->export_for_template($this);
+
         return $this->render_from_template('core/action_menu', $context);
     }
 
@@ -1646,20 +1696,6 @@ class core_renderer extends renderer_base {
     /**
      * Prints a nice side block with an optional header.
      *
-     * The content is described
-     * by a {@link core_renderer::block_contents} object.
-     *
-     * <div id="inst{$instanceid}" class="block_{$blockname} block">
-     *      <div class="header"></div>
-     *      <div class="content">
-     *          ...CONTENT...
-     *          <div class="footer">
-     *          </div>
-     *      </div>
-     *      <div class="annotation">
-     *      </div>
-     * </div>
-     *
      * @param block_contents $bc HTML for the content
      * @param string $region the region the block is appearing in.
      * @return string the HTML to be output.
@@ -1669,144 +1705,29 @@ class core_renderer extends renderer_base {
         if (empty($bc->blockinstanceid) || !strip_tags($bc->title)) {
             $bc->collapsible = block_contents::NOT_HIDEABLE;
         }
-        if (!empty($bc->blockinstanceid)) {
-            $bc->attributes['data-instanceid'] = $bc->blockinstanceid;
-        }
-        $skiptitle = strip_tags($bc->title);
-        if ($bc->blockinstanceid && !empty($skiptitle)) {
-            $bc->attributes['aria-labelledby'] = 'instance-'.$bc->blockinstanceid.'-header';
-        } else if (!empty($bc->arialabel)) {
-            $bc->attributes['aria-label'] = $bc->arialabel;
-        }
-        if ($bc->dockable) {
-            $bc->attributes['data-dockable'] = 1;
-        }
-        if ($bc->collapsible == block_contents::HIDDEN) {
-            $bc->add_class('hidden');
-        }
-        if (!empty($bc->controls)) {
-            $bc->add_class('block_with_controls');
-        }
-
 
-        if (empty($skiptitle)) {
-            $output = '';
-            $skipdest = '';
-        } else {
-            $output = html_writer::link('#sb-'.$bc->skipid, get_string('skipa', 'access', $skiptitle),
-                      array('class' => 'skip skip-block', 'id' => 'fsb-' . $bc->skipid));
-            $skipdest = html_writer::span('', 'skip-block-to',
-                      array('id' => 'sb-' . $bc->skipid));
+        $id = !empty($bc->attributes['id']) ? $bc->attributes['id'] : uniqid('block-');
+        $context = new stdClass();
+        $context->skipid = $bc->skipid;
+        $context->blockinstanceid = $bc->blockinstanceid;
+        $context->dockable = $bc->dockable;
+        $context->id = $id;
+        $context->hidden = $bc->collapsible == block_contents::HIDDEN;
+        $context->skiptitle = strip_tags($bc->title);
+        $context->showskiplink = !empty($context->skiptitle);
+        $context->arialabel = $bc->arialabel;
+        $context->ariarole = !empty($bc->attributes['role']) ? $bc->attributes['role'] : 'complementary';
+        $context->type = $bc->attributes['data-block'];
+        $context->title = $bc->title;
+        $context->content = $bc->content;
+        $context->annotation = $bc->annotation;
+        $context->footer = $bc->footer;
+        $context->hascontrols = !empty($bc->controls);
+        if ($context->hascontrols) {
+            $context->controls = $this->block_controls($bc->controls, $id);
         }
 
-        $output .= html_writer::start_tag('div', $bc->attributes);
-
-        $output .= $this->block_header($bc);
-        $output .= $this->block_content($bc);
-
-        $output .= html_writer::end_tag('div');
-
-        $output .= $this->block_annotation($bc);
-
-        $output .= $skipdest;
-
-        $this->init_block_hider_js($bc);
-        return $output;
-    }
-
-    /**
-     * Produces a header for a block
-     *
-     * @param block_contents $bc
-     * @return string
-     */
-    protected function block_header(block_contents $bc) {
-
-        $title = '';
-        if ($bc->title) {
-            $attributes = array();
-            if ($bc->blockinstanceid) {
-                $attributes['id'] = 'instance-'.$bc->blockinstanceid.'-header';
-            }
-            $title = html_writer::tag('h2', $bc->title, $attributes);
-        }
-
-        $blockid = null;
-        if (isset($bc->attributes['id'])) {
-            $blockid = $bc->attributes['id'];
-        }
-        $controlshtml = $this->block_controls($bc->controls, $blockid);
-
-        $output = '';
-        if ($title || $controlshtml) {
-            $output .= html_writer::tag('div', html_writer::tag('div', html_writer::tag('div', '', array('class'=>'block_action')). $title . $controlshtml, array('class' => 'title')), array('class' => 'header'));
-        }
-        return $output;
-    }
-
-    /**
-     * Produces the content area for a block
-     *
-     * @param block_contents $bc
-     * @return string
-     */
-    protected function block_content(block_contents $bc) {
-        $output = html_writer::start_tag('div', array('class' => 'content'));
-        if (!$bc->title && !$this->block_controls($bc->controls)) {
-            $output .= html_writer::tag('div', '', array('class'=>'block_action notitle'));
-        }
-        $output .= $bc->content;
-        $output .= $this->block_footer($bc);
-        $output .= html_writer::end_tag('div');
-
-        return $output;
-    }
-
-    /**
-     * Produces the footer for a block
-     *
-     * @param block_contents $bc
-     * @return string
-     */
-    protected function block_footer(block_contents $bc) {
-        $output = '';
-        if ($bc->footer) {
-            $output .= html_writer::tag('div', $bc->footer, array('class' => 'footer'));
-        }
-        return $output;
-    }
-
-    /**
-     * Produces the annotation for a block
-     *
-     * @param block_contents $bc
-     * @return string
-     */
-    protected function block_annotation(block_contents $bc) {
-        $output = '';
-        if ($bc->annotation) {
-            $output .= html_writer::tag('div', $bc->annotation, array('class' => 'blockannotation'));
-        }
-        return $output;
-    }
-
-    /**
-     * Calls the JS require function to hide a block.
-     *
-     * @param block_contents $bc A block_contents object
-     */
-    protected function init_block_hider_js(block_contents $bc) {
-        if (!empty($bc->attributes['id']) and $bc->collapsible != block_contents::NOT_HIDEABLE) {
-            $config = new stdClass;
-            $config->id = $bc->attributes['id'];
-            $config->title = strip_tags($bc->title);
-            $config->preference = 'block' . $bc->blockinstanceid . 'hidden';
-            $config->tooltipVisible = get_string('hideblocka', 'access', $config->title);
-            $config->tooltipHidden = get_string('showblocka', 'access', $config->title);
-
-            $this->page->requires->js_init_call('M.util.init_block_hider', array($config));
-            user_preference_allow_ajax_update($config->preference, PARAM_BOOL);
-        }
+        return $this->render_from_template('core/block', $context);
     }
 
     /**
@@ -2055,50 +1976,7 @@ class core_renderer extends renderer_base {
      * @return string HTML fragment
      */
     protected function render_single_button(single_button $button) {
-        $attributes = array('type'     => 'submit',
-                            'value'    => $button->label,
-                            'disabled' => $button->disabled ? 'disabled' : null,
-                            'title'    => $button->tooltip);
-
-        if ($button->actions) {
-            $id = html_writer::random_id('single_button');
-            $attributes['id'] = $id;
-            foreach ($button->actions as $action) {
-                $this->add_action_handler($action, $id);
-            }
-        }
-
-        // first the input element
-        $output = html_writer::empty_tag('input', $attributes);
-
-        // then hidden fields
-        $params = $button->url->params();
-        if ($button->method === 'post') {
-            $params['sesskey'] = sesskey();
-        }
-        foreach ($params as $var => $val) {
-            $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => $var, 'value' => $val));
-        }
-
-        // then div wrapper for xhtml strictness
-        $output = html_writer::tag('div', $output);
-
-        // now the form itself around it
-        if ($button->method === 'get') {
-            $url = $button->url->out_omit_querystring(true); // url without params, the anchor part allowed
-        } else {
-            $url = $button->url->out_omit_querystring();     // url without params, the anchor part not allowed
-        }
-        if ($url === '') {
-            $url = '#'; // there has to be always some action
-        }
-        $attributes = array('method' => $button->method,
-                            'action' => $url,
-                            'id'     => $button->formid);
-        $output = html_writer::tag('form', $output, $attributes);
-
-        // and finally one more wrapper with class
-        return html_writer::tag('div', $output, array('class' => $button->class));
+        return $this->render_from_template('core/single_button', $button->export_for_template($this));
     }
 
     /**
@@ -2471,7 +2349,8 @@ class core_renderer extends renderer_base {
      * @return string HTML fragment
      */
     protected function render_help_icon(help_icon $helpicon) {
-        return $this->render_from_template('core/help_icon', $helpicon->export_for_template($this));
+        $context = $helpicon->export_for_template($this);
+        return $this->render_from_template('core/help_icon', $context);
     }
 
     /**
@@ -3154,7 +3033,7 @@ EOD;
     public function box_start($classes = 'generalbox', $id = null, $attributes = array()) {
         $this->opencontainers->push('box', html_writer::end_tag('div'));
         $attributes['id'] = $id;
-        $attributes['class'] = 'box ' . renderer_base::prepare_classes($classes);
+        $attributes['class'] = 'box py-3 ' . renderer_base::prepare_classes($classes);
         return html_writer::start_tag('div', $attributes);
     }
 
@@ -3532,39 +3411,11 @@ EOD;
     }
 
     /**
-     * Return the navbar content so that it can be echoed out by the layout
-     *
-     * @return string XHTML navbar
+     * This renders the navbar.
+     * Uses bootstrap compatible html.
      */
     public function navbar() {
-        $items = $this->page->navbar->get_items();
-        $itemcount = count($items);
-        if ($itemcount === 0) {
-            return '';
-        }
-
-        $htmlblocks = array();
-        // Iterate the navarray and display each node
-        $separator = get_separator();
-        for ($i=0;$i < $itemcount;$i++) {
-            $item = $items[$i];
-            $item->hideicon = true;
-            if ($i===0) {
-                $content = html_writer::tag('li', $this->render($item));
-            } else {
-                $content = html_writer::tag('li', $separator.$this->render($item));
-            }
-            $htmlblocks[] = $content;
-        }
-
-        //accessibility: heading for navbar list  (MDL-20446)
-        $navbarcontent = html_writer::tag('span', get_string('pagepath'),
-                array('class' => 'accesshide', 'id' => 'navbar-label'));
-        $navbarcontent .= html_writer::tag('nav',
-                html_writer::tag('ul', join('', $htmlblocks)),
-                array('aria-labelledby' => 'navbar-label'));
-        // XHTML
-        return $navbarcontent;
+        return $this->render_from_template('core/navbar', $this->page->navbar);
     }
 
     /**
@@ -3719,14 +3570,44 @@ EOD;
      */
     public function custom_menu($custommenuitems = '') {
         global $CFG;
+
         if (empty($custommenuitems) && !empty($CFG->custommenuitems)) {
             $custommenuitems = $CFG->custommenuitems;
         }
-        if (empty($custommenuitems)) {
-            return '';
+        $custommenu = new custom_menu($custommenuitems, current_language());
+        return $this->render_custom_menu($custommenu);
+    }
+
+    /**
+     * We want to show the custom menus as a list of links in the footer on small screens.
+     * Just return the menu object exported so we can render it differently.
+     */
+    public function custom_menu_flat() {
+        global $CFG;
+        $custommenuitems = '';
+
+        if (empty($custommenuitems) && !empty($CFG->custommenuitems)) {
+            $custommenuitems = $CFG->custommenuitems;
         }
         $custommenu = new custom_menu($custommenuitems, current_language());
-        return $this->render($custommenu);
+        $langs = get_string_manager()->get_list_of_translations();
+        $haslangmenu = $this->lang_menu() != '';
+
+        if ($haslangmenu) {
+            $strlang = get_string('language');
+            $currentlang = current_language();
+            if (isset($langs[$currentlang])) {
+                $currentlang = $langs[$currentlang];
+            } else {
+                $currentlang = $strlang;
+            }
+            $this->language = $custommenu->add($currentlang, new moodle_url('#'), $strlang, 10000);
+            foreach ($langs as $langtype => $langname) {
+                $this->language->add($langname, new moodle_url($this->page->url, array('lang' => $langtype)), $langname);
+            }
+        }
+
+        return $custommenu->export_for_template($this);
     }
 
     /**
@@ -3740,31 +3621,35 @@ EOD;
      * @return string
      */
     protected function render_custom_menu(custom_menu $menu) {
-        static $menucount = 0;
-        // If the menu has no children return an empty string
-        if (!$menu->has_children()) {
+        global $CFG;
+
+        $langs = get_string_manager()->get_list_of_translations();
+        $haslangmenu = $this->lang_menu() != '';
+
+        if (!$menu->has_children() && !$haslangmenu) {
             return '';
         }
-        // Increment the menu count. This is used for ID's that get worked with
-        // in JavaScript as is essential
-        $menucount++;
-        // Initialise this custom menu (the custom menu object is contained in javascript-static
-        $jscode = js_writer::function_call_with_Y('M.core_custom_menu.init', array('custom_menu_'.$menucount));
-        $jscode = "(function(){{$jscode}})";
-        $this->page->requires->yui_module('node-menunav', $jscode);
-        // Build the root nodes as required by YUI
-        $content = html_writer::start_tag('div', array('id'=>'custom_menu_'.$menucount, 'class'=>'yui3-menu yui3-menu-horizontal javascript-disabled custom-menu'));
-        $content .= html_writer::start_tag('div', array('class'=>'yui3-menu-content'));
-        $content .= html_writer::start_tag('ul');
-        // Render each child
+
+        if ($haslangmenu) {
+            $strlang = get_string('language');
+            $currentlang = current_language();
+            if (isset($langs[$currentlang])) {
+                $currentlang = $langs[$currentlang];
+            } else {
+                $currentlang = $strlang;
+            }
+            $this->language = $menu->add($currentlang, new moodle_url('#'), $strlang, 10000);
+            foreach ($langs as $langtype => $langname) {
+                $this->language->add($langname, new moodle_url($this->page->url, array('lang' => $langtype)), $langname);
+            }
+        }
+
+        $content = '';
         foreach ($menu->get_children() as $item) {
-            $content .= $this->render_custom_menu_item($item);
+            $context = $item->export_for_template($this);
+            $content .= $this->render_from_template('core/custom_menu_item', $context);
         }
-        // Close the open tags
-        $content .= html_writer::end_tag('ul');
-        $content .= html_writer::end_tag('div');
-        $content .= html_writer::end_tag('div');
-        // Return the custom menu
+
         return $content;
     }
 
@@ -3897,12 +3782,8 @@ EOD;
         if (empty($tabtree->subtree)) {
             return '';
         }
-        $str = '';
-        $str .= html_writer::start_tag('div', array('class' => 'tabtree'));
-        $str .= $this->render_tabobject($tabtree);
-        $str .= html_writer::end_tag('div').
-                html_writer::tag('div', ' ', array('class' => 'clearer'));
-        return $str;
+        $data = $tabtree->export_for_template($this);
+        return $this->render_from_template('core/tabtree', $data);
     }
 
     /**
@@ -4029,36 +3910,7 @@ EOD;
      * @return string
      */
     public function body_css_classes(array $additionalclasses = array()) {
-        // Add a class for each block region on the page.
-        // We use the block manager here because the theme object makes get_string calls.
-        $usedregions = array();
-        foreach ($this->page->blocks->get_regions() as $region) {
-            $additionalclasses[] = 'has-region-'.$region;
-            if ($this->page->blocks->region_has_content($region, $this)) {
-                $additionalclasses[] = 'used-region-'.$region;
-                $usedregions[] = $region;
-            } else {
-                $additionalclasses[] = 'empty-region-'.$region;
-            }
-            if ($this->page->blocks->region_completely_docked($region, $this)) {
-                $additionalclasses[] = 'docked-region-'.$region;
-            }
-        }
-        if (!$usedregions) {
-            // No regions means there is only content, add 'content-only' class.
-            $additionalclasses[] = 'content-only';
-        } else if (count($usedregions) === 1) {
-            // Add the -only class for the only used region.
-            $region = array_shift($usedregions);
-            $additionalclasses[] = $region . '-only';
-        }
-        foreach ($this->page->layout_options as $option => $value) {
-            if ($value) {
-                $additionalclasses[] = 'layout-option-'.$option;
-            }
-        }
-        $css = $this->page->bodyclasses .' '. join(' ', $additionalclasses);
-        return $css;
+        return $this->page->bodyclasses . ' ' . implode(' ', $additionalclasses);
     }
 
     /**
@@ -4161,29 +4013,7 @@ EOD;
      * @return string The output.
      */
     public function render_preferences_groups(preferences_groups $renderable) {
-        $html = '';
-        $html .= html_writer::start_div('row-fluid');
-        $html .= html_writer::start_tag('div', array('class' => 'span12 preferences-groups'));
-        $i = 0;
-        $open = false;
-        foreach ($renderable->groups as $group) {
-            if ($i == 0 || $i % 3 == 0) {
-                if ($open) {
-                    $html .= html_writer::end_tag('div');
-                }
-                $html .= html_writer::start_tag('div', array('class' => 'row-fluid'));
-                $open = true;
-            }
-            $html .= $this->render($group);
-            $i++;
-        }
-
-        $html .= html_writer::end_tag('div');
-
-        $html .= html_writer::end_tag('ul');
-        $html .= html_writer::end_tag('div');
-        $html .= html_writer::end_div();
-        return $html;
+        return $this->render_from_template('core/preferences_groups', $renderable);
     }
 
     /**
@@ -4209,13 +4039,20 @@ EOD;
     }
 
     public function context_header($headerinfo = null, $headinglevel = 1) {
-        global $DB, $USER, $CFG;
+        global $DB, $USER, $CFG, $SITE;
         require_once($CFG->dirroot . '/user/lib.php');
         $context = $this->page->context;
         $heading = null;
         $imagedata = null;
         $subheader = null;
         $userbuttons = null;
+
+        if ($this->should_display_main_logo($headinglevel)) {
+            $sitename = format_string($SITE->fullname, true, array('context' => context_course::instance(SITEID)));
+            return html_writer::div(html_writer::empty_tag('img', [
+                    'src' => $this->get_logo_url(null, 150), 'alt' => $sitename]), 'logo');
+        }
+
         // Make sure to use the heading if it has been set.
         if (isset($headerinfo['heading'])) {
             $heading = $headerinfo['heading'];
@@ -4372,15 +4209,232 @@ EOD;
      * @return string HTML to display the main header.
      */
     public function full_header() {
-        $html = html_writer::start_tag('header', array('id' => 'page-header', 'class' => 'clearfix'));
-        $html .= $this->context_header();
-        $html .= html_writer::start_div('clearfix', array('id' => 'page-navbar'));
-        $html .= html_writer::tag('div', $this->navbar(), array('class' => 'breadcrumb-nav'));
-        $html .= html_writer::div($this->page_heading_button(), 'breadcrumb-button');
-        $html .= html_writer::end_div();
-        $html .= html_writer::tag('div', $this->course_header(), array('id' => 'course-header'));
-        $html .= html_writer::end_tag('header');
-        return $html;
+        global $PAGE;
+
+        $header = new stdClass();
+        $header->settingsmenu = $this->context_header_settings_menu();
+        $header->contextheader = $this->context_header();
+        $header->hasnavbar = empty($PAGE->layout_options['nonavbar']);
+        $header->navbar = $this->navbar();
+        $header->pageheadingbutton = $this->page_heading_button();
+        $header->courseheader = $this->course_header();
+        return $this->render_from_template('core/full_header', $header);
+    }
+
+    /**
+     * This is an optional menu that can be added to a layout by a theme. It contains the
+     * menu for the course administration, only on the course main page.
+     *
+     * @return string
+     */
+    public function context_header_settings_menu() {
+        $context = $this->page->context;
+        $menu = new action_menu();
+
+        $items = $this->page->navbar->get_items();
+        $currentnode = end($items);
+
+        $showcoursemenu = false;
+        $showfrontpagemenu = false;
+        $showusermenu = false;
+
+        // We are on the course home page.
+        if (($context->contextlevel == CONTEXT_COURSE) &&
+                !empty($currentnode) &&
+                ($currentnode->type == navigation_node::TYPE_COURSE || $currentnode->type == navigation_node::TYPE_SECTION)) {
+            $showcoursemenu = true;
+        }
+
+        $courseformat = course_get_format($this->page->course);
+        // This is a single activity course format, always show the course menu on the activity main page.
+        if ($context->contextlevel == CONTEXT_MODULE &&
+                !$courseformat->has_view_page()) {
+
+            $this->page->navigation->initialise();
+            $activenode = $this->page->navigation->find_active_node();
+            // If the settings menu has been forced then show the menu.
+            if ($this->page->is_settings_menu_forced()) {
+                $showcoursemenu = true;
+            } else if (!empty($activenode) && ($activenode->type == navigation_node::TYPE_ACTIVITY ||
+                            $activenode->type == navigation_node::TYPE_RESOURCE)) {
+
+                // We only want to show the menu on the first page of the activity. This means
+                // the breadcrumb has no additional nodes.
+                if ($currentnode && ($currentnode->key == $activenode->key && $currentnode->type == $activenode->type)) {
+                    $showcoursemenu = true;
+                }
+            }
+        }
+
+        // This is the site front page.
+        if ($context->contextlevel == CONTEXT_COURSE &&
+                !empty($currentnode) &&
+                $currentnode->key === 'home') {
+            $showfrontpagemenu = true;
+        }
+
+        // This is the user profile page.
+        if ($context->contextlevel == CONTEXT_USER &&
+                !empty($currentnode) &&
+                ($currentnode->key === 'myprofile')) {
+            $showusermenu = true;
+        }
+
+        if ($showfrontpagemenu) {
+            $settingsnode = $this->page->settingsnav->find('frontpage', navigation_node::TYPE_SETTING);
+            if ($settingsnode) {
+                // Build an action menu based on the visible nodes from this navigation tree.
+                $skipped = $this->build_action_menu_from_navigation($menu, $settingsnode, false, true);
+
+                // We only add a list to the full settings menu if we didn't include every node in the short menu.
+                if ($skipped) {
+                    $text = get_string('morenavigationlinks');
+                    $url = new moodle_url('/course/admin.php', array('courseid' => $this->page->course->id));
+                    $link = new action_link($url, $text, null, null, new pix_icon('t/edit', $text));
+                    $menu->add_secondary_action($link);
+                }
+            }
+        } else if ($showcoursemenu) {
+            $settingsnode = $this->page->settingsnav->find('courseadmin', navigation_node::TYPE_COURSE);
+            if ($settingsnode) {
+                // Build an action menu based on the visible nodes from this navigation tree.
+                $skipped = $this->build_action_menu_from_navigation($menu, $settingsnode, false, true);
+
+                // We only add a list to the full settings menu if we didn't include every node in the short menu.
+                if ($skipped) {
+                    $text = get_string('morenavigationlinks');
+                    $url = new moodle_url('/course/admin.php', array('courseid' => $this->page->course->id));
+                    $link = new action_link($url, $text, null, null, new pix_icon('t/edit', $text));
+                    $menu->add_secondary_action($link);
+                }
+            }
+        } else if ($showusermenu) {
+            // Get the course admin node from the settings navigation.
+            $settingsnode = $this->page->settingsnav->find('useraccount', navigation_node::TYPE_CONTAINER);
+            if ($settingsnode) {
+                // Build an action menu based on the visible nodes from this navigation tree.
+                $this->build_action_menu_from_navigation($menu, $settingsnode);
+            }
+        }
+
+        return $this->render($menu);
+    }
+
+    /**
+     * Take a node in the nav tree and make an action menu out of it.
+     * The links are injected in the action menu.
+     *
+     * @param action_menu $menu
+     * @param navigation_node $node
+     * @param boolean $indent
+     * @param boolean $onlytopleafnodes
+     * @return boolean nodesskipped - True if nodes were skipped in building the menu
+     */
+    protected function build_action_menu_from_navigation(action_menu $menu,
+            navigation_node $node,
+            $indent = false,
+            $onlytopleafnodes = false) {
+        $skipped = false;
+        // Build an action menu based on the visible nodes from this navigation tree.
+        foreach ($node->children as $menuitem) {
+            if ($menuitem->display) {
+                if ($onlytopleafnodes && $menuitem->children->count()) {
+                    $skipped = true;
+                    continue;
+                }
+                if ($menuitem->action) {
+                    if ($menuitem->action instanceof action_link) {
+                        $link = $menuitem->action;
+                        // Give preference to setting icon over action icon.
+                        if (!empty($menuitem->icon)) {
+                            $link->icon = $menuitem->icon;
+                        }
+                    } else {
+                        $link = new action_link($menuitem->action, $menuitem->text, null, null, $menuitem->icon);
+                    }
+                } else {
+                    if ($onlytopleafnodes) {
+                        $skipped = true;
+                        continue;
+                    }
+                    $link = new action_link(new moodle_url('#'), $menuitem->text, null, ['disabled' => true], $menuitem->icon);
+                }
+                if ($indent) {
+                    $link->add_class('ml-4');
+                }
+                if (!empty($menuitem->classes)) {
+                    $link->add_class(implode(" ", $menuitem->classes));
+                }
+
+                $menu->add_secondary_action($link);
+                $skipped = $skipped || $this->build_action_menu_from_navigation($menu, $menuitem, true);
+            }
+        }
+        return $skipped;
+    }
+
+    /**
+     * This is an optional menu that can be added to a layout by a theme. It contains the
+     * menu for the most specific thing from the settings block. E.g. Module administration.
+     *
+     * @return string
+     */
+    public function region_main_settings_menu() {
+        $context = $this->page->context;
+        $menu = new action_menu();
+
+        if ($context->contextlevel == CONTEXT_MODULE) {
+
+            $this->page->navigation->initialise();
+            $node = $this->page->navigation->find_active_node();
+            $buildmenu = false;
+            // If the settings menu has been forced then show the menu.
+            if ($this->page->is_settings_menu_forced()) {
+                $buildmenu = true;
+            } else if (!empty($node) && ($node->type == navigation_node::TYPE_ACTIVITY ||
+                            $node->type == navigation_node::TYPE_RESOURCE)) {
+
+                $items = $this->page->navbar->get_items();
+                $navbarnode = end($items);
+                // We only want to show the menu on the first page of the activity. This means
+                // the breadcrumb has no additional nodes.
+                if ($navbarnode && ($navbarnode->key === $node->key && $navbarnode->type == $node->type)) {
+                    $buildmenu = true;
+                }
+            }
+            if ($buildmenu) {
+                // Get the course admin node from the settings navigation.
+                $node = $this->page->settingsnav->find('modulesettings', navigation_node::TYPE_SETTING);
+                if ($node) {
+                    // Build an action menu based on the visible nodes from this navigation tree.
+                    $this->build_action_menu_from_navigation($menu, $node);
+                }
+            }
+
+        } else if ($context->contextlevel == CONTEXT_COURSECAT) {
+            // For course category context, show category settings menu, if we're on the course category page.
+            if ($this->page->pagetype === 'course-index-category') {
+                $node = $this->page->settingsnav->find('categorysettings', navigation_node::TYPE_CONTAINER);
+                if ($node) {
+                    // Build an action menu based on the visible nodes from this navigation tree.
+                    $this->build_action_menu_from_navigation($menu, $node);
+                }
+            }
+
+        } else {
+            $items = $this->page->navbar->get_items();
+            $navbarnode = end($items);
+
+            if ($navbarnode && ($navbarnode->key === 'participants')) {
+                $node = $this->page->settingsnav->find('users', navigation_node::TYPE_CONTAINER);
+                if ($node) {
+                    // Build an action menu based on the visible nodes from this navigation tree.
+                    $this->build_action_menu_from_navigation($menu, $node);
+                }
+
+            }
+        }
+        return $this->render($menu);
     }
 
     /**
@@ -4462,7 +4516,7 @@ EOD;
      * @return string
      */
     public function render_login(\core_auth\output\login $form) {
-        global $CFG;
+        global $CFG, $SITE;
 
         $context = $form->export_for_template($this);
 
@@ -4473,6 +4527,13 @@ EOD;
             $context->cookieshelpiconformatted = $this->help_icon('cookiesenabled');
         }
         $context->errorformatted = $this->error_text($context->error);
+        $url = $this->get_logo_url();
+        if ($url) {
+            $url = $url->out(false);
+        }
+        $context->logourl = $url;
+        $context->sitename = format_string($SITE->fullname, true,
+                ['context' => context_course::instance(SITEID), "escape" => false]);
 
         return $this->render_from_template('core/loginform', $context);
     }
@@ -4556,7 +4617,16 @@ EOD;
      * @return string
      */
     public function render_login_signup_form($form) {
+        global $SITE;
+
         $context = $form->export_for_template($this);
+        $url = $this->get_logo_url();
+        if ($url) {
+            $url = $url->out(false);
+        }
+        $context['logourl'] = $url;
+        $context['sitename'] = format_string($SITE->fullname, true,
+                ['context' => context_course::instance(SITEID), "escape" => false]);
 
         return $this->render_from_template('core/signup_form_layout', $context);
     }
@@ -5023,6 +5093,15 @@ class core_renderer_maintenance extends core_renderer {
         return '';
     }
 
+    /**
+     * Secure login info.
+     *
+     * @return string
+     */
+    public function secure_login_info() {
+        return $this->login_info(false);
+    }
+
     /**
      * Does nothing. The maintenance renderer cannot produce user pictures.
      *
index 1a918e9..b582821 100644 (file)
 
 namespace theme_boost\output;
 
-use coding_exception;
-use html_writer;
-use tabobject;
-use tabtree;
-use custom_menu_item;
-use custom_menu;
-use block_contents;
-use navigation_node;
-use action_link;
-use stdClass;
 use moodle_url;
-use preferences_groups;
-use action_menu;
-use help_icon;
-use single_button;
-use context_course;
-use pix_icon;
 
 defined('MOODLE_INTERNAL') || die;
 
@@ -46,70 +30,6 @@ defined('MOODLE_INTERNAL') || die;
 
 class core_renderer extends \core_renderer {
 
-    /** @var custom_menu_item language The language menu if created */
-    protected $language = null;
-
-    /**
-     * Outputs the opening section of a box.
-     *
-     * @param string $classes A space-separated list of CSS classes
-     * @param string $id An optional ID
-     * @param array $attributes An array of other attributes to give the box.
-     * @return string the HTML to output.
-     */
-    public function box_start($classes = 'generalbox', $id = null, $attributes = array()) {
-        if (is_array($classes)) {
-            $classes = implode(' ', $classes);
-        }
-        return parent::box_start($classes . ' py-3', $id, $attributes);
-    }
-
-    /**
-     * Wrapper for header elements.
-     *
-     * @return string HTML to display the main header.
-     */
-    public function full_header() {
-        global $PAGE;
-
-        $header = new stdClass();
-        $header->settingsmenu = $this->context_header_settings_menu();
-        $header->contextheader = $this->context_header();
-        $header->hasnavbar = empty($PAGE->layout_options['nonavbar']);
-        $header->navbar = $this->navbar();
-        $header->pageheadingbutton = $this->page_heading_button();
-        $header->courseheader = $this->course_header();
-        return $this->render_from_template('theme_boost/header', $header);
-    }
-
-    /**
-     * The standard tags that should be included in the <head> tag
-     * including a meta description for the front page
-     *
-     * @return string HTML fragment.
-     */
-    public function standard_head_html() {
-        global $SITE, $PAGE;
-
-        $output = parent::standard_head_html();
-        if ($PAGE->pagelayout == 'frontpage') {
-            $summary = s(strip_tags(format_text($SITE->summary, FORMAT_HTML)));
-            if (!empty($summary)) {
-                $output .= "<meta name=\"description\" content=\"$summary\" />\n";
-            }
-        }
-
-        return $output;
-    }
-
-    /*
-     * This renders the navbar.
-     * Uses bootstrap compatible html.
-     */
-    public function navbar() {
-        return $this->render_from_template('core/navbar', $this->page->navbar);
-    }
-
     /**
      * We don't like these...
      *
@@ -117,577 +37,4 @@ class core_renderer extends \core_renderer {
     public function edit_button(moodle_url $url) {
         return '';
     }
-
-    /**
-     * Override to inject the logo.
-     *
-     * @param array $headerinfo The header info.
-     * @param int $headinglevel What level the 'h' tag will be.
-     * @return string HTML for the header bar.
-     */
-    public function context_header($headerinfo = null, $headinglevel = 1) {
-        global $SITE;
-
-        if ($this->should_display_main_logo($headinglevel)) {
-            $sitename = format_string($SITE->fullname, true, array('context' => context_course::instance(SITEID)));
-            return html_writer::div(html_writer::empty_tag('img', [
-                'src' => $this->get_logo_url(null, 150), 'alt' => $sitename]), 'logo');
-        }
-
-        return parent::context_header($headerinfo, $headinglevel);
-    }
-
-    /**
-     * Get the compact logo URL.
-     *
-     * @return string
-     */
-    public function get_compact_logo_url($maxwidth = 100, $maxheight = 100) {
-        return parent::get_compact_logo_url(null, 70);
-    }
-
-    /**
-     * Whether we should display the main logo.
-     *
-     * @return bool
-     */
-    public function should_display_main_logo($headinglevel = 1) {
-        global $PAGE;
-
-        // Only render the logo if we're on the front page or login page and the we have a logo.
-        $logo = $this->get_logo_url();
-        if ($headinglevel == 1 && !empty($logo)) {
-            if ($PAGE->pagelayout == 'frontpage' || $PAGE->pagelayout == 'login') {
-                return true;
-            }
-        }
-
-        return false;
-    }
-    /**
-     * Whether we should display the logo in the navbar.
-     *
-     * We will when there are no main logos, and we have compact logo.
-     *
-     * @return bool
-     */
-    public function should_display_navbar_logo() {
-        $logo = $this->get_compact_logo_url();
-        return !empty($logo) && !$this->should_display_main_logo();
-    }
-
-    /*
-     * Overriding the custom_menu function ensures the custom menu is
-     * always shown, even if no menu items are configured in the global
-     * theme settings page.
-     */
-    public function custom_menu($custommenuitems = '') {
-        global $CFG;
-
-        if (empty($custommenuitems) && !empty($CFG->custommenuitems)) {
-            $custommenuitems = $CFG->custommenuitems;
-        }
-        $custommenu = new custom_menu($custommenuitems, current_language());
-        return $this->render_custom_menu($custommenu);
-    }
-
-    /**
-     * We want to show the custom menus as a list of links in the footer on small screens.
-     * Just return the menu object exported so we can render it differently.
-     */
-    public function custom_menu_flat() {
-        global $CFG;
-        $custommenuitems = '';
-
-        if (empty($custommenuitems) && !empty($CFG->custommenuitems)) {
-            $custommenuitems = $CFG->custommenuitems;
-        }
-        $custommenu = new custom_menu($custommenuitems, current_language());
-        $langs = get_string_manager()->get_list_of_translations();
-        $haslangmenu = $this->lang_menu() != '';
-
-        if ($haslangmenu) {
-            $strlang = get_string('language');
-            $currentlang = current_language();
-            if (isset($langs[$currentlang])) {
-                $currentlang = $langs[$currentlang];
-            } else {
-                $currentlang = $strlang;
-            }
-            $this->language = $custommenu->add($currentlang, new moodle_url('#'), $strlang, 10000);
-            foreach ($langs as $langtype => $langname) {
-                $this->language->add($langname, new moodle_url($this->page->url, array('lang' => $langtype)), $langname);
-            }
-        }
-
-        return $custommenu->export_for_template($this);
-    }
-
-    /*
-     * This renders the bootstrap top menu.
-     *
-     * This renderer is needed to enable the Bootstrap style navigation.
-     */
-    protected function render_custom_menu(custom_menu $menu) {
-        global $CFG;
-
-        $langs = get_string_manager()->get_list_of_translations();
-        $haslangmenu = $this->lang_menu() != '';
-
-        if (!$menu->has_children() && !$haslangmenu) {
-            return '';
-        }
-
-        if ($haslangmenu) {
-            $strlang = get_string('language');
-            $currentlang = current_language();
-            if (isset($langs[$currentlang])) {
-                $currentlang = $langs[$currentlang];
-            } else {
-                $currentlang = $strlang;
-            }
-            $this->language = $menu->add($currentlang, new moodle_url('#'), $strlang, 10000);
-            foreach ($langs as $langtype => $langname) {
-                $this->language->add($langname, new moodle_url($this->page->url, array('lang' => $langtype)), $langname);
-            }
-        }
-
-        $content = '';
-        foreach ($menu->get_children() as $item) {
-            $context = $item->export_for_template($this);
-            $content .= $this->render_from_template('core/custom_menu_item', $context);
-        }
-
-        return $content;
-    }
-
-    /**
-     * This code renders the navbar button to control the display of the custom menu
-     * on smaller screens.
-     *
-     * Do not display the button if the menu is empty.
-     *
-     * @return string HTML fragment
-     */
-    public function navbar_button() {
-        global $CFG;
-
-        if (empty($CFG->custommenuitems) && $this->lang_menu() == '') {
-            return '';
-        }
-
-        $iconbar = html_writer::tag('span', '', array('class' => 'icon-bar'));
-        $button = html_writer::tag('a', $iconbar . "\n" . $iconbar. "\n" . $iconbar, array(
-            'class'       => 'btn btn-navbar',
-            'data-toggle' => 'collapse',
-            'data-target' => '.nav-collapse'
-        ));
-        return $button;
-    }
-
-    /**
-     * Renders tabtree
-     *
-     * @param tabtree $tabtree
-     * @return string
-     */
-    protected function render_tabtree(tabtree $tabtree) {
-        if (empty($tabtree->subtree)) {
-            return '';
-        }
-        $data = $tabtree->export_for_template($this);
-        return $this->render_from_template('core/tabtree', $data);
-    }
-
-    /**
-     * Renders tabobject (part of tabtree)
-     *
-     * This function is called from {@link core_renderer::render_tabtree()}
-     * and also it calls itself when printing the $tabobject subtree recursively.
-     *
-     * @param tabobject $tabobject
-     * @return string HTML fragment
-     */
-    protected function render_tabobject(tabobject $tab) {
-        throw new coding_exception('Tab objects should not be directly rendered.');
-    }
-
-    /**
-     * Prints a nice side block with an optional header.
-     *
-     * @param block_contents $bc HTML for the content
-     * @param string $region the region the block is appearing in.
-     * @return string the HTML to be output.
-     */
-    public function block(block_contents $bc, $region) {
-        $bc = clone($bc); // Avoid messing up the object passed in.
-        if (empty($bc->blockinstanceid) || !strip_tags($bc->title)) {
-            $bc->collapsible = block_contents::NOT_HIDEABLE;
-        }
-
-        $id = !empty($bc->attributes['id']) ? $bc->attributes['id'] : uniqid('block-');
-        $context = new stdClass();
-        $context->skipid = $bc->skipid;
-        $context->blockinstanceid = $bc->blockinstanceid;
-        $context->dockable = $bc->dockable;
-        $context->id = $id;
-        $context->hidden = $bc->collapsible == block_contents::HIDDEN;
-        $context->skiptitle = strip_tags($bc->title);
-        $context->showskiplink = !empty($context->skiptitle);
-        $context->arialabel = $bc->arialabel;
-        $context->ariarole = !empty($bc->attributes['role']) ? $bc->attributes['role'] : 'complementary';
-        $context->type = $bc->attributes['data-block'];
-        $context->title = $bc->title;
-        $context->content = $bc->content;
-        $context->annotation = $bc->annotation;
-        $context->footer = $bc->footer;
-        $context->hascontrols = !empty($bc->controls);
-        if ($context->hascontrols) {
-            $context->controls = $this->block_controls($bc->controls, $id);
-        }
-
-        return $this->render_from_template('core/block', $context);
-    }
-
-    /**
-     * Returns the CSS classes to apply to the body tag.
-     *
-     * @since Moodle 2.5.1 2.6
-     * @param array $additionalclasses Any additional classes to apply.
-     * @return string
-     */
-    public function body_css_classes(array $additionalclasses = array()) {
-        return $this->page->bodyclasses . ' ' . implode(' ', $additionalclasses);
-    }
-
-    /**
-     * Renders preferences groups.
-     *
-     * @param  preferences_groups $renderable The renderable
-     * @return string The output.
-     */
-    public function render_preferences_groups(preferences_groups $renderable) {
-        return $this->render_from_template('core/preferences_groups', $renderable);
-    }
-
-    /**
-     * Renders an action menu component.
-     *
-     * @param action_menu $menu
-     * @return string HTML
-     */
-    public function render_action_menu(action_menu $menu) {
-
-        // We don't want the class icon there!
-        foreach ($menu->get_secondary_actions() as $action) {
-            if ($action instanceof \action_menu_link && $action->has_class('icon')) {
-                $action->attributes['class'] = preg_replace('/(^|\s+)icon(\s+|$)/i', '', $action->attributes['class']);
-            }
-        }
-
-        if ($menu->is_empty()) {
-            return '';
-        }
-        $context = $menu->export_for_template($this);
-
-        return $this->render_from_template('core/action_menu', $context);
-    }
-
-    /**
-     * Implementation of user image rendering.
-     *
-     * @param help_icon $helpicon A help icon instance
-     * @return string HTML fragment
-     */
-    protected function render_help_icon(help_icon $helpicon) {
-        $context = $helpicon->export_for_template($this);
-        return $this->render_from_template('core/help_icon', $context);
-    }
-
-    /**
-     * Renders a single button widget.
-     *
-     * This will return HTML to display a form containing a single button.
-     *
-     * @param single_button $button
-     * @return string HTML fragment
-     */
-    protected function render_single_button(single_button $button) {
-        return $this->render_from_template('core/single_button', $button->export_for_template($this));
-    }
-
-    /**
-     * Renders the login form.
-     *
-     * @param \core_auth\output\login $form The renderable.
-     * @return string
-     */
-    public function render_login(\core_auth\output\login $form) {
-        global $CFG, $SITE;
-
-        $context = $form->export_for_template($this);
-
-        // Override because rendering is not supported in template yet.
-        if ($CFG->rememberusername == 0) {
-            $context->cookieshelpiconformatted = $this->help_icon('cookiesenabledonlysession');
-        } else {
-            $context->cookieshelpiconformatted = $this->help_icon('cookiesenabled');
-        }
-        $context->errorformatted = $this->error_text($context->error);
-        $url = $this->get_logo_url();
-        if ($url) {
-            $url = $url->out(false);
-        }
-        $context->logourl = $url;
-        $context->sitename = format_string($SITE->fullname, true,
-            ['context' => context_course::instance(SITEID), "escape" => false]);
-
-        return $this->render_from_template('core/loginform', $context);
-    }
-
-    /**
-     * Render the login signup form into a nice template for the theme.
-     *
-     * @param mform $form
-     * @return string
-     */
-    public function render_login_signup_form($form) {
-        global $SITE;
-
-        $context = $form->export_for_template($this);
-        $url = $this->get_logo_url();
-        if ($url) {
-            $url = $url->out(false);
-        }
-        $context['logourl'] = $url;
-        $context['sitename'] = format_string($SITE->fullname, true,
-            ['context' => context_course::instance(SITEID), "escape" => false]);
-
-        return $this->render_from_template('core/signup_form_layout', $context);
-    }
-
-    /**
-     * This is an optional menu that can be added to a layout by a theme. It contains the
-     * menu for the course administration, only on the course main page.
-     *
-     * @return string
-     */
-    public function context_header_settings_menu() {
-        $context = $this->page->context;
-        $menu = new action_menu();
-
-        $items = $this->page->navbar->get_items();
-        $currentnode = end($items);
-
-        $showcoursemenu = false;
-        $showfrontpagemenu = false;
-        $showusermenu = false;
-
-        // We are on the course home page.
-        if (($context->contextlevel == CONTEXT_COURSE) &&
-                !empty($currentnode) &&
-                ($currentnode->type == navigation_node::TYPE_COURSE || $currentnode->type == navigation_node::TYPE_SECTION)) {
-            $showcoursemenu = true;
-        }
-
-        $courseformat = course_get_format($this->page->course);
-        // This is a single activity course format, always show the course menu on the activity main page.
-        if ($context->contextlevel == CONTEXT_MODULE &&
-                !$courseformat->has_view_page()) {
-
-            $this->page->navigation->initialise();
-            $activenode = $this->page->navigation->find_active_node();
-            // If the settings menu has been forced then show the menu.
-            if ($this->page->is_settings_menu_forced()) {
-                $showcoursemenu = true;
-            } else if (!empty($activenode) && ($activenode->type == navigation_node::TYPE_ACTIVITY ||
-                    $activenode->type == navigation_node::TYPE_RESOURCE)) {
-
-                // We only want to show the menu on the first page of the activity. This means
-                // the breadcrumb has no additional nodes.
-                if ($currentnode && ($currentnode->key == $activenode->key && $currentnode->type == $activenode->type)) {
-                    $showcoursemenu = true;
-                }
-            }
-        }
-
-        // This is the site front page.
-        if ($context->contextlevel == CONTEXT_COURSE &&
-                !empty($currentnode) &&
-                $currentnode->key === 'home') {
-            $showfrontpagemenu = true;
-        }
-
-        // This is the user profile page.
-        if ($context->contextlevel == CONTEXT_USER &&
-                !empty($currentnode) &&
-                ($currentnode->key === 'myprofile')) {
-            $showusermenu = true;
-        }
-
-        if ($showfrontpagemenu) {
-            $settingsnode = $this->page->settingsnav->find('frontpage', navigation_node::TYPE_SETTING);
-            if ($settingsnode) {
-                // Build an action menu based on the visible nodes from this navigation tree.
-                $skipped = $this->build_action_menu_from_navigation($menu, $settingsnode, false, true);
-
-                // We only add a list to the full settings menu if we didn't include every node in the short menu.
-                if ($skipped) {
-                    $text = get_string('morenavigationlinks');
-                    $url = new moodle_url('/course/admin.php', array('courseid' => $this->page->course->id));
-                    $link = new action_link($url, $text, null, null, new pix_icon('t/edit', ''));
-                    $menu->add_secondary_action($link);
-                }
-            }
-        } else if ($showcoursemenu) {
-            $settingsnode = $this->page->settingsnav->find('courseadmin', navigation_node::TYPE_COURSE);
-            if ($settingsnode) {
-                // Build an action menu based on the visible nodes from this navigation tree.
-                $skipped = $this->build_action_menu_from_navigation($menu, $settingsnode, false, true);
-
-                // We only add a list to the full settings menu if we didn't include every node in the short menu.
-                if ($skipped) {
-                    $text = get_string('morenavigationlinks');
-                    $url = new moodle_url('/course/admin.php', array('courseid' => $this->page->course->id));
-                    $link = new action_link($url, $text, null, null, new pix_icon('t/edit', ''));
-                    $menu->add_secondary_action($link);
-                }
-            }
-        } else if ($showusermenu) {
-            // Get the course admin node from the settings navigation.
-            $settingsnode = $this->page->settingsnav->find('useraccount', navigation_node::TYPE_CONTAINER);
-            if ($settingsnode) {
-                // Build an action menu based on the visible nodes from this navigation tree.
-                $this->build_action_menu_from_navigation($menu, $settingsnode);
-            }
-        }
-
-        return $this->render($menu);
-    }
-
-    /**
-     * This is an optional menu that can be added to a layout by a theme. It contains the
-     * menu for the most specific thing from the settings block. E.g. Module administration.
-     *
-     * @return string
-     */
-    public function region_main_settings_menu() {
-        $context = $this->page->context;
-        $menu = new action_menu();
-
-        if ($context->contextlevel == CONTEXT_MODULE) {
-
-            $this->page->navigation->initialise();
-            $node = $this->page->navigation->find_active_node();
-            $buildmenu = false;
-            // If the settings menu has been forced then show the menu.
-            if ($this->page->is_settings_menu_forced()) {
-                $buildmenu = true;
-            } else if (!empty($node) && ($node->type == navigation_node::TYPE_ACTIVITY ||
-                    $node->type == navigation_node::TYPE_RESOURCE)) {
-
-                $items = $this->page->navbar->get_items();
-                $navbarnode = end($items);
-                // We only want to show the menu on the first page of the activity. This means
-                // the breadcrumb has no additional nodes.
-                if ($navbarnode && ($navbarnode->key === $node->key && $navbarnode->type == $node->type)) {
-                    $buildmenu = true;
-                }
-            }
-            if ($buildmenu) {
-                // Get the course admin node from the settings navigation.
-                $node = $this->page->settingsnav->find('modulesettings', navigation_node::TYPE_SETTING);
-                if ($node) {
-                    // Build an action menu based on the visible nodes from this navigation tree.
-                    $this->build_action_menu_from_navigation($menu, $node);
-                }
-            }
-
-        } else if ($context->contextlevel == CONTEXT_COURSECAT) {
-            // For course category context, show category settings menu, if we're on the course category page.
-            if ($this->page->pagetype === 'course-index-category') {
-                $node = $this->page->settingsnav->find('categorysettings', navigation_node::TYPE_CONTAINER);
-                if ($node) {
-                    // Build an action menu based on the visible nodes from this navigation tree.
-                    $this->build_action_menu_from_navigation($menu, $node);
-                }
-            }
-
-        } else {
-            $items = $this->page->navbar->get_items();
-            $navbarnode = end($items);
-
-            if ($navbarnode && ($navbarnode->key === 'participants')) {
-                $node = $this->page->settingsnav->find('users', navigation_node::TYPE_CONTAINER);
-                if ($node) {
-                    // Build an action menu based on the visible nodes from this navigation tree.
-                    $this->build_action_menu_from_navigation($menu, $node);
-                }
-
-            }
-        }
-        return $this->render($menu);
-    }
-
-    /**
-     * Take a node in the nav tree and make an action menu out of it.
-     * The links are injected in the action menu.
-     *
-     * @param action_menu $menu
-     * @param navigation_node $node
-     * @param boolean $indent
-     * @param boolean $onlytopleafnodes
-     * @return boolean nodesskipped - True if nodes were skipped in building the menu
-     */
-    protected function build_action_menu_from_navigation(action_menu $menu,
-                                                       navigation_node $node,
-                                                       $indent = false,
-                                                       $onlytopleafnodes = false) {
-        $skipped = false;
-        // Build an action menu based on the visible nodes from this navigation tree.
-        foreach ($node->children as $menuitem) {
-            if ($menuitem->display) {
-                if ($onlytopleafnodes && $menuitem->children->count()) {
-                    $skipped = true;
-                    continue;
-                }
-                if ($menuitem->action) {
-                    if ($menuitem->action instanceof action_link) {
-                        $link = $menuitem->action;
-                        // Give preference to setting icon over action icon.
-                        if (!empty($menuitem->icon)) {
-                            $link->icon = $menuitem->icon;
-                        }
-                    } else {
-                        $link = new action_link($menuitem->action, $menuitem->text, null, null, $menuitem->icon);
-                    }
-                } else {
-                    if ($onlytopleafnodes) {
-                        $skipped = true;
-                        continue;
-                    }
-                    $link = new action_link(new moodle_url('#'), $menuitem->text, null, ['disabled' => true], $menuitem->icon);
-                }
-                if ($indent) {
-                    $link->add_class('ml-4');
-                }
-                if (!empty($menuitem->classes)) {
-                    $link->add_class(implode(" ", $menuitem->classes));
-                }
-
-                $menu->add_secondary_action($link);
-                $skipped = $skipped || $this->build_action_menu_from_navigation($menu, $menuitem, true);
-            }
-        }
-        return $skipped;
-    }
-
-    /**
-     * Secure login info.
-     *
-     * @return string
-     */
-    public function secure_login_info() {
-        return $this->login_info(false);
-    }
-}
+}
\ No newline at end of file
index d1c4cb3..b30335a 100644 (file)
@@ -39,13 +39,13 @@ use moodle_url;
 class block_settings_renderer extends \block_settings_renderer {
 
     public function search_form(moodle_url $formtarget, $searchvalue) {
-        $content = html_writer::start_tag('form', array('class'=>'adminsearchform', 'method'=>'get', 'action'=>$formtarget, 'role' => 'search'));
-        $content .= html_writer::start_tag('div');
-        $content .= html_writer::tag('label', s(get_string('searchinsettings', 'admin')), array('for'=>'adminsearchquery', 'class'=>'accesshide'));
-        $content .= html_writer::empty_tag('input', array('id'=>'adminsearchquery', 'type'=>'text', 'name'=>'query', 'value'=>s($searchvalue)));
-        $content .= html_writer::empty_tag('input', array('type'=>'submit', 'value'=>s(get_string('search'))));
-        $content .= html_writer::end_tag('div');
-        $content .= html_writer::end_tag('form');
+        $content = \html_writer::start_tag('form', array('class'=>'adminsearchform', 'method'=>'get', 'action'=>$formtarget, 'role' => 'search'));
+        $content .= \html_writer::start_tag('div');
+        $content .= \html_writer::tag('label', s(get_string('searchinsettings', 'admin')), array('for'=>'adminsearchquery', 'class'=>'accesshide'));
+        $content .= \html_writer::empty_tag('input', array('id'=>'adminsearchquery', 'type'=>'text', 'name'=>'query', 'value'=>s($searchvalue)));
+        $content .= \html_writer::empty_tag('input', array('type'=>'submit', 'value'=>s(get_string('search'))));
+        $content .= \html_writer::end_tag('div');
+        $content .= \html_writer::end_tag('form');
         return $content;
     }
 
index a79a6ef..a05ad71 100644 (file)
@@ -71,18 +71,18 @@ class course_renderer extends \core_course_renderer {
         $strsearchcourses= get_string("searchcourses");
         $searchurl = new moodle_url('/course/search.php');
 
-        $output = html_writer::start_tag('form', array('id' => $formid, 'action' => $searchurl, 'method' => 'get'));
-        $output .= html_writer::start_tag('fieldset', array('class' => 'coursesearchbox invisiblefieldset'));
-        $output .= html_writer::tag('label', $strsearchcourses.': ', array('for' => $inputid));
-        $output .= html_writer::empty_tag('input', array('type' => 'text', 'id' => $inputid,
+        $output = \html_writer::start_tag('form', array('id' => $formid, 'action' => $searchurl, 'method' => 'get'));
+        $output .= \html_writer::start_tag('fieldset', array('class' => 'coursesearchbox invisiblefieldset'));
+        $output .= \html_writer::tag('label', $strsearchcourses.': ', array('for' => $inputid));
+        $output .= \html_writer::empty_tag('input', array('type' => 'text', 'id' => $inputid,
                 'size' => $inputsize, 'name' => 'search', 'value' => s($value)));
-        $output .= html_writer::empty_tag('input', array('type' => 'submit',
+        $output .= \html_writer::empty_tag('input', array('type' => 'submit',
                 'value' => get_string('go')));
-        $output .= html_writer::end_tag('fieldset');
+        $output .= \html_writer::end_tag('fieldset');
         if ($format != 'navbar') {
             $output .= $this->output->help_icon("coursesearch", "core");
         }
-        $output .= html_writer::end_tag('form');
+        $output .= \html_writer::end_tag('form');
 
         return $output;
     }
index fbf0448..4022c5b 100644 (file)
@@ -417,11 +417,11 @@ class files_renderer extends \core_files_renderer {
      * Default contents is one text input field with name="s"
      */
     public function repository_default_searchform() {
-        $searchinput = html_writer::label(get_string('searchrepo', 'repository'),
+        $searchinput = \html_writer::label(get_string('searchrepo', 'repository'),
                 'reposearch', false, array('class' => 'accesshide'));
-        $searchinput .= html_writer::empty_tag('input', array('type' => 'text',
+        $searchinput .= \html_writer::empty_tag('input', array('type' => 'text',
                 'id' => 'reposearch', 'name' => 's', 'value' => get_string('search', 'repository')));
-        $str = html_writer::tag('div', $searchinput, array('class' => "fp-def-search"));
+        $str = \html_writer::tag('div', $searchinput, array('class' => "fp-def-search"));
 
         return $str;
     }
index c804c52..a63e443 100644 (file)
@@ -66,7 +66,7 @@ class renderer extends \core_course_management_renderer {
         if (!is_null($id)) {
             $attributes['id'] = $id;
         }
-        return html_writer::start_div($class, $attributes);
+        return \html_writer::start_div($class, $attributes);
     }
 
     /**
@@ -112,7 +112,7 @@ class renderer extends \core_course_management_renderer {
         if (!is_null($id)) {
             $attributes['id'] = $id;
         }
-        return html_writer::start_div($class, $attributes);
+        return \html_writer::start_div($class, $attributes);
     }
 
     /**
@@ -125,13 +125,13 @@ class renderer extends \core_course_management_renderer {
         $details = \core_course\management\helper::get_course_detail_array($course);
         $fullname = $details['fullname']['value'];
 
-        $html  = html_writer::start_div('course-detail');
-        $html .= html_writer::tag('h3', $fullname, array('id' => 'course-detail-title', 'tabindex' => '0'));
+        $html  = \html_writer::start_div('course-detail');
+        $html .= \html_writer::tag('h3', $fullname, array('id' => 'course-detail-title', 'tabindex' => '0'));
         $html .= $this->course_detail_actions($course);
         foreach ($details as $class => $data) {
             $html .= $this->detail_pair($data['key'], $data['value'], $class);
         }
-        $html .= html_writer::end_div();
+        $html .= \html_writer::end_div();
         return $html;
     }
 
@@ -167,16 +167,16 @@ class renderer extends \core_course_management_renderer {
         $strsearchcourses = get_string("searchcourses");
         $searchurl = new moodle_url('/course/management.php');
 
-        $output = html_writer::start_tag('form', array('id' => $formid, 'action' => $searchurl, 'method' => 'get',
+        $output = \html_writer::start_tag('form', array('id' => $formid, 'action' => $searchurl, 'method' => 'get',
                 'class' => 'form-inline'));
-        $output .= html_writer::start_tag('fieldset', array('class' => 'coursesearchbox invisiblefieldset m-y-1'));
-        $output .= html_writer::tag('label', $strsearchcourses, array('for' => $inputid));
-        $output .= html_writer::empty_tag('input', array('type' => 'text', 'id' => $inputid, 'size' => $inputsize,
+        $output .= \html_writer::start_tag('fieldset', array('class' => 'coursesearchbox invisiblefieldset m-y-1'));
+        $output .= \html_writer::tag('label', $strsearchcourses, array('for' => $inputid));
+        $output .= \html_writer::empty_tag('input', array('type' => 'text', 'id' => $inputid, 'size' => $inputsize,
                 'name' => 'search', 'value' => s($value), 'class' => 'form-control m-x-1'));
-        $output .= html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('go'),
+        $output .= \html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('go'),
                 'class' => 'btn btn-secondary'));
-        $output .= html_writer::end_tag('fieldset');
-        $output .= html_writer::end_tag('form');
+        $output .= \html_writer::end_tag('fieldset');
+        $output .= \html_writer::end_tag('form');
 
         return $output;
     }
@@ -209,10 +209,10 @@ class renderer extends \core_course_management_renderer {
                 'aria-labelledby' => 'category-listing-title'
         );
 
-        $html  = html_writer::start_div('category-listing');
-        $html .= html_writer::tag('h3', get_string('categories'), array('id' => 'category-listing-title'));
+        $html  = \html_writer::start_div('category-listing');
+        $html .= \html_writer::tag('h3', get_string('categories'), array('id' => 'category-listing-title'));
         $html .= $this->category_listing_actions($category);
-        $html .= html_writer::start_tag('ul', $attributes);
+        $html .= \html_writer::start_tag('ul', $attributes);
         foreach ($listing as $listitem) {
             // Render each category in the listing.
             $subcategories = array();
@@ -227,9 +227,9 @@ class renderer extends \core_course_management_renderer {
                     $selectedparents
             );
         }
-        $html .= html_writer::end_tag('ul');
+        $html .= \html_writer::end_tag('ul');
         $html .= $this->category_bulk_actions($category);
-        $html .= html_writer::end_div();
+        $html .= \html_writer::end_div();
         return $html;
     }
 
@@ -286,7 +286,7 @@ class renderer extends \core_course_management_renderer {
         $viewcaturl = new moodle_url('/course/management.php', array('categoryid' => $category->id));
         if ($isexpanded) {
             $icon = $this->output->pix_icon('t/switch_minus', get_string('collapse'), 'moodle', array('class' => 'tree-icon', 'title' => ''));
-            $icon = html_writer::link(
+            $icon = \html_writer::link(
                     $viewcaturl,
                     $icon,
                     array(
@@ -298,7 +298,7 @@ class renderer extends \core_course_management_renderer {
             );
         } else if ($isexpandable) {
             $icon = $this->output->pix_icon('t/switch_plus', get_string('expand'), 'moodle', array('class' => 'tree-icon', 'title' => ''));
-            $icon = html_writer::link(
+            $icon = \html_writer::link(
                     $viewcaturl,
                     $icon,
                     array(
@@ -313,16 +313,16 @@ class renderer extends \core_course_management_renderer {
                     '',
                     'moodle',
                     array('class' => 'tree-icon'));
-            $icon = html_writer::span($icon, 'float-left');
+            $icon = \html_writer::span($icon, 'float-left');
         }
         $actions = \core_course\management\helper::get_category_listitem_actions($category);
         $hasactions = !empty($actions) || $category->can_create_course();
 
-        $html = html_writer::start_tag('li', $attributes);
-        $html .= html_writer::start_div('clearfix');
-        $html .= html_writer::start_div('float-left ba-checkbox');
-        $html .= html_writer::empty_tag('input', $bcatinput).'&nbsp;';
-        $html .= html_writer::end_div();
+        $html = \html_writer::start_tag('li', $attributes);
+        $html .= \html_writer::start_div('clearfix');
+        $html .= \html_writer::start_div('float-left ba-checkbox');
+        $html .= \html_writer::empty_tag('input', $bcatinput).'&nbsp;';
+        $html .= \html_writer::end_div();
         $html .= $icon;
         if ($hasactions) {
             $textattributes = array('class' => 'float-left categoryname');
@@ -332,26 +332,26 @@ class renderer extends \core_course_management_renderer {
         if (isset($textlabel)) {
             $textattributes['aria-label'] = $textlabel;
         }
-        $html .= html_writer::link($viewcaturl, $text, $textattributes);
-        $html .= html_writer::start_div('float-right');
+        $html .= \html_writer::link($viewcaturl, $text, $textattributes);
+        $html .= \html_writer::start_div('float-right');
         if ($category->idnumber) {
-            $html .= html_writer::tag('span', s($category->idnumber), array('class' => 'dimmed idnumber'));
+            $html .= \html_writer::tag('span', s($category->idnumber), array('class' => 'dimmed idnumber'));
         }
         if ($hasactions) {
             $html .= $this->category_listitem_actions($category, $actions);
         }
         $countid = 'course-count-'.$category->id;
-        $html .= html_writer::span(
-                html_writer::span($category->get_courses_count()) .
-                html_writer::span(get_string('courses'), 'accesshide', array('id' => $countid)) .
+        $html .= \html_writer::span(
+                \html_writer::span($category->get_courses_count()) .
+                \html_writer::span(get_string('courses'), 'accesshide', array('id' => $countid)) .
                 $courseicon,
                 'course-count dimmed',
                 array('aria-labelledby' => $countid)
         );
-        $html .= html_writer::end_div();
-        $html .= html_writer::end_div();
+        $html .= \html_writer::end_div();
+        $html .= \html_writer::end_div();
         if ($isexpanded) {
-            $html .= html_writer::start_tag('ul',
+            $html .= \html_writer::start_tag('ul',
                     array('class' => 'ml', 'role' => 'group', 'id' => 'subcategoryof'.$category->id));
             $catatlevel = \core_course\management\helper::get_expanded_categories($category->path);
             $catatlevel[] = array_shift($selectedcategories);
@@ -366,9 +366,9 @@ class renderer extends \core_course_management_renderer {
                         $selectedcategories
                 );
             }
-            $html .= html_writer::end_tag('ul');
+            $html .= \html_writer::end_tag('ul');
         }
-        $html .= html_writer::end_tag('li');
+        $html .= \html_writer::end_tag('li');
         return $html;
     }
 
@@ -392,15 +392,15 @@ class renderer extends \core_course_management_renderer {
 
         if ($cancreatecategory) {
             $url = new moodle_url('/course/editcategory.php', array('parent' => $category->id));
-            $actions[] = html_writer::link($url, get_string('createnewcategory'));
+            $actions[] = \html_writer::link($url, get_string('createnewcategory'));
         }
         if (core_course_category::can_approve_course_requests()) {
-            $actions[] = html_writer::link(new moodle_url('/course/pending.php'), get_string('coursespending'));
+            $actions[] = \html_writer::link(new moodle_url('/course/pending.php'), get_string('coursespending'));
         }
         if (count($actions) === 0) {
             return '';
         }
-        return html_writer::div(join(' | ', $actions), 'listing-actions category-listing-actions');
+        return \html_writer::div(join(' | ', $actions), 'listing-actions category-listing-actions');
     }
 
     /**
@@ -418,11 +418,11 @@ class renderer extends \core_course_management_renderer {
             $viewmode = 'default') {
 
         if ($category === null) {
-            $html = html_writer::start_div('select-a-category');
-            $html .= html_writer::tag('h3', get_string('courses'),
+            $html = \html_writer::start_div('select-a-category');
+            $html .= \html_writer::tag('h3', get_string('courses'),
                     array('id' => 'course-listing-title', 'tabindex' => '0'));
             $html .= $this->output->notification(get_string('selectacategory'), 'notifymessage');
-            $html .= html_writer::end_div();
+            $html .= \html_writer::end_div();
             return $html;
         }
 
@@ -446,25 +446,25 @@ class renderer extends \core_course_management_renderer {
             $class .= ' lastpage';
         }
 
-        $html  = html_writer::start_div('course-listing'.$class, array(
+        $html  = \html_writer::start_div('course-listing'.$class, array(
                 'data-category' => $category->id,
                 'data-page' => $page,
                 'data-totalpages' => $totalpages,
                 'data-totalcourses' => $totalcourses,
                 'data-canmoveoutof' => $category->can_move_courses_out_of() && $category->can_move_courses_into()
         ));
-        $html .= html_writer::tag('h3', $category->get_formatted_name(),
+        $html .= \html_writer::tag('h3', $category->get_formatted_name(),
                 array('id' => 'course-listing-title', 'tabindex' => '0'));
         $html .= $this->course_listing_actions($category, $course, $perpage);
         $html .= $this->listing_pagination($category, $page, $perpage, false, $viewmode);
-        $html .= html_writer::start_tag('ul', array('class' => 'ml course-list', 'role' => 'group'));
+        $html .= \html_writer::start_tag('ul', array('class' => 'ml course-list', 'role' => 'group'));
         foreach ($category->get_courses($options) as $listitem) {
             $html .= $this->course_listitem($category, $listitem, $courseid);
         }
-        $html .= html_writer::end_tag('ul');
+        $html .= \html_writer::end_tag('ul');
         $html .= $this->listing_pagination($category, $page, $perpage, true, $viewmode);
         $html .= $this->course_bulk_actions($category);
-        $html .= html_writer::end_div();
+        $html .= \html_writer::end_div();
         return $html;
     }
 
@@ -503,26 +503,26 @@ class renderer extends \core_course_management_renderer {
 
         $viewcourseurl = new moodle_url($this->page->url, array('courseid' => $course->id));
 
-        $html  = html_writer::start_tag('li', $attributes);
-        $html .= html_writer::start_div('clearfix');
+        $html  = \html_writer::start_tag('li', $attributes);
+        $html .= \html_writer::start_div('clearfix');
 
         if ($category->can_resort_courses()) {
             // In order for dnd to be available the user must be able to resort the category children..
-            $html .= html_writer::div($this->output->pix_icon('i/move_2d', get_string('dndcourse')), 'float-left drag-handle');
+            $html .= \html_writer::div($this->output->pix_icon('i/move_2d', get_string('dndcourse')), 'float-left drag-handle');
         }
 
-        $html .= html_writer::start_div('ba-checkbox float-left');
-        $html .= html_writer::empty_tag('input', $bulkcourseinput).'&nbsp;';
-        $html .= html_writer::end_div();
-        $html .= html_writer::link($viewcourseurl, $text, array('class' => 'float-left coursename'));
-        $html .= html_writer::start_div('float-right');
+        $html .= \html_writer::start_div('ba-checkbox float-left');
+        $html .= \html_writer::empty_tag('input', $bulkcourseinput).'&nbsp;';
+        $html .= \html_writer::end_div();
+        $html .= \html_writer::link($viewcourseurl, $text, array('class' => 'float-left coursename'));
+        $html .= \html_writer::start_div('float-right');
         if ($course->idnumber) {
-            $html .= html_writer::tag('span', s($course->idnumber), array('class' => 'dimmed idnumber'));
+            $html .= \html_writer::tag('span', s($course->idnumber), array('class' => 'dimmed idnumber'));
         }
         $html .= $this->course_listitem_actions($category, $course);
-        $html .= html_writer::end_div();
-        $html .= html_writer::end_div();
-        $html .= html_writer::end_tag('li');
+        $html .= \html_writer::end_div();
+        $html .= \html_writer::end_div();
+        $html .= \html_writer::end_tag('li');
         return $html;
     }
 
@@ -540,12 +540,12 @@ class renderer extends \core_course_management_renderer {
         $actions = array();
         if ($category->can_create_course()) {
             $url = new moodle_url('/course/edit.php', array('category' => $category->id, 'returnto' => 'catmanage'));
-            $actions[] = html_writer::link($url, get_string('createnewcourse'));
+            $actions[] = \html_writer::link($url, get_string('createnewcourse'));
         }
         if ($category->can_request_course()) {
             // Request a new course.
             $url = new moodle_url('/course/request.php', array('return' => 'management'));
-            $actions[] = html_writer::link($url, get_string('requestcourse'));
+            $actions[] = \html_writer::link($url, get_string('requestcourse'));
         }
         if ($category->can_resort_courses()) {
             $params = $this->page->url->params();
@@ -604,7 +604,7 @@ class renderer extends \core_course_management_renderer {
         $menu->attributes['class'] .= ' courses-per-page';
         $menu->set_menu_trigger(get_string('perpagea', 'moodle', $perpage));
         $actions[] = $this->render($menu);
-        return html_writer::div(join(' | ', $actions), 'listing-actions course-listing-actions');
+        return \html_writer::div(join(' | ', $actions), 'listing-actions course-listing-actions');
     }
 
     /**
@@ -631,15 +631,15 @@ class renderer extends \core_course_management_renderer {
         $last = false;
         $i = $page * $perpage;
 
-        $html  = html_writer::start_div('course-listing', array(
+        $html  = \html_writer::start_div('course-listing', array(
                 'data-category' => 'search',
                 'data-page' => $page,
                 'data-totalpages' => $totalpages,
                 'data-totalcourses' => $totalcourses
         ));
-        $html .= html_writer::tag('h3', get_string('courses'));
+        $html .= \html_writer::tag('h3', get_string('courses'));
         $html .= $this->search_pagination($totalcourses, $page, $perpage);
-        $html .= html_writer::start_tag('ul', array('class' => 'ml'));
+        $html .= \html_writer::start_tag('ul', array('class' => 'ml'));
         foreach ($courses as $listitem) {
             $i++;
             if ($i == $totalcourses) {
@@ -648,10 +648,10 @@ class renderer extends \core_course_management_renderer {
             $html .= $this->search_listitem($listitem, $courseid, $first, $last);
             $first = false;
         }
-        $html .= html_writer::end_tag('ul');
+        $html .= \html_writer::end_tag('ul');
         $html .= $this->search_pagination($totalcourses, $page, $perpage, true, $search);
         $html .= $this->course_search_bulk_actions();
-        $html .= html_writer::end_div();
+        $html .= \html_writer::end_div();
         return $html;
     }
 
@@ -687,21 +687,21 @@ class renderer extends \core_course_management_renderer {
         $viewcourseurl = new moodle_url($this->page->url, array('courseid' => $course->id));
         $categoryname = core_course_category::get($course->category)->get_formatted_name();
 
-        $html  = html_writer::start_tag('li', $attributes);
-        $html .= html_writer::start_div('clearfix');
-        $html .= html_writer::start_div('float-left');
+        $html  = \html_writer::start_tag('li', $attributes);
+        $html .= \html_writer::start_div('clearfix');
+        $html .= \html_writer::start_div('float-left');
         if ($bulkcourseinput) {
-            $html .= html_writer::empty_tag('input', $bulkcourseinput).'&nbsp;';
+            $html .= \html_writer::empty_tag('input', $bulkcourseinput).'&nbsp;';
         }
-        $html .= html_writer::end_div();
-        $html .= html_writer::link($viewcourseurl, $text, array('class' => 'float-left coursename'));
-        $html .= html_writer::tag('span', $categoryname, array('class' => 'float-left categoryname'));
-        $html .= html_writer::start_div('float-right');
+        $html .= \html_writer::end_div();
+        $html .= \html_writer::link($viewcourseurl, $text, array('class' => 'float-left coursename'));
+        $html .= \html_writer::tag('span', $categoryname, array('class' => 'float-left categoryname'));
+        $html .= \html_writer::start_div('float-right');
         $html .= $this->search_listitem_actions($course);
-        $html .= html_writer::tag('span', s($course->idnumber), array('class' => 'dimmed idnumber'));
-        $html .= html_writer::end_div();
-        $html .= html_writer::end_div();
-        $html .= html_writer::end_tag('li');
+        $html .= \html_writer::tag('span', s($course->idnumber), array('class' => 'dimmed idnumber'));
+        $html .= \html_writer::end_div();
+        $html .= \html_writer::end_div();
+        $html .= \html_writer::end_tag('li');
         return $html;
     }
 
@@ -714,10 +714,10 @@ class renderer extends \core_course_management_renderer {
      * @return string
      */
     protected function detail_pair($key, $value, $class ='') {
-        $html = html_writer::start_div('detail-pair row yui3-g '.preg_replace('#[^a-zA-Z0-9_\-]#', '-', $class));
-        $html .= html_writer::div(html_writer::span($key), 'pair-key span3 col-md-3 yui3-u-1-4');
-        $html .= html_writer::div(html_writer::span($value), 'pair-value span9 col-md-9 m-b-1 yui3-u-3-4 form-inline');
-        $html .= html_writer::end_div();
+        $html = \html_writer::start_div('detail-pair row yui3-g '.preg_replace('#[^a-zA-Z0-9_\-]#', '-', $class));
+        $html .= \html_writer::div(html_writer::span($key), 'pair-key span3 col-md-3 yui3-u-1-4');
+        $html .= \html_writer::div(html_writer::span($value), 'pair-value span9 col-md-9 m-b-1 yui3-u-3-4 form-inline');
+        $html .= \html_writer::end_div();
         return $html;
     }
 
@@ -736,7 +736,7 @@ class renderer extends \core_course_management_renderer {
         foreach ($actions as $action) {
             $options[] = $this->action_link($action['url'], $action['string']);
         }
-        return html_writer::div(join(' | ', $options), 'listing-actions course-detail-listing-actions');
+        return \html_writer::div(join(' | ', $options), 'listing-actions course-detail-listing-actions');
     }
 
 }
diff --git a/theme/bootstrapbase/classes/output/core_renderer.php b/theme/bootstrapbase/classes/output/core_renderer.php
new file mode 100644 (file)
index 0000000..0a53221
--- /dev/null
@@ -0,0 +1,470 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace theme_bootstrapbase\output;
+
+use coding_exception;
+use \html_writer;
+use tabobject;
+use tabtree;
+use custom_menu_item;
+use custom_menu;
+use block_contents;
+use navigation_node;
+use action_link;
+use stdClass;
+use moodle_url;
+use preferences_groups;
+use action_menu;
+use help_icon;
+use single_button;
+use context_course;
+use pix_icon;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Renderers to align Moodle's HTML with that expected by Bootstrap
+ *
+ * @package    theme_bootstrapbase
+ * @copyright  2012 Bas Brands, www.basbrands.nl
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+class core_renderer extends \core_renderer {
+
+    /**
+     * Wrapper for header elements.
+     *
+     * @return string HTML to display the main header.
+     */
+    public function full_header() {
+        $html = \html_writer::start_tag('header', array('id' => 'page-header', 'class' => 'clearfix'));
+        $html .= $this->context_header();
+        $html .= \html_writer::start_div('clearfix', array('id' => 'page-navbar'));
+        $html .= \html_writer::tag('div', $this->navbar(), array('class' => 'breadcrumb-nav'));
+        $html .= \html_writer::div($this->page_heading_button(), 'breadcrumb-button');
+        $html .= html_writer::end_div();
+        $html .= html_writer::tag('div', $this->course_header(), array('id' => 'course-header'));
+        $html .= html_writer::end_tag('header');
+        return $html;
+    }
+
+    /**
+     * Return the navbar content so that it can be echoed out by the layout
+     *
+     * @return string XHTML navbar
+     */
+    public function navbar() {
+        $items = $this->page->navbar->get_items();
+        $itemcount = count($items);
+        if ($itemcount === 0) {
+            return '';
+        }
+
+        $htmlblocks = array();
+        // Iterate the navarray and display each node
+        $separator = get_separator();
+        for ($i=0;$i < $itemcount;$i++) {
+            $item = $items[$i];
+            $item->hideicon = true;
+            if ($i===0) {
+                $content = html_writer::tag('li', $this->render($item));
+            } else {
+                $content = html_writer::tag('li', $separator.$this->render($item));
+            }
+            $htmlblocks[] = $content;
+        }
+
+        //accessibility: heading for navbar list  (MDL-20446)
+        $navbarcontent = html_writer::tag('span', get_string('pagepath'),
+                array('class' => 'accesshide', 'id' => 'navbar-label'));
+        $navbarcontent .= html_writer::tag('nav',
+                html_writer::tag('ul', join('', $htmlblocks)),
+                array('aria-labelledby' => 'navbar-label'));
+        // XHTML
+        return $navbarcontent;
+    }
+
+    /**
+     * Returns HTML to display a "Turn editing on/off" button in a form.
+     *
+     * @param moodle_url $url The URL + params to send through when clicking the button
+     * @return string HTML the button
+     */
+    public function edit_button(moodle_url $url) {
+
+        $url->param('sesskey', sesskey());
+        if ($this->page->user_is_editing()) {
+            $url->param('edit', 'off');
+            $editstring = get_string('turneditingoff');
+        } else {
+            $url->param('edit', 'on');
+            $editstring = get_string('turneditingon');
+        }
+
+        return $this->single_button($url, $editstring);
+    }
+
+    /**
+     * Get the compact logo URL.
+     *
+     * @return string
+     */
+    public function get_compact_logo_url($maxwidth = 100, $maxheight = 100) {
+        return parent::get_compact_logo_url(null, 70);
+    }
+
+    /*
+     * Overriding the custom_menu function ensures the custom menu is
+     * always shown, even if no menu items are configured in the global
+     * theme settings page.
+     */
+    public function custom_menu($custommenuitems = '') {
+        global $CFG;
+        if (empty($custommenuitems) && !empty($CFG->custommenuitems)) {
+            $custommenuitems = $CFG->custommenuitems;
+        }
+        if (empty($custommenuitems)) {
+            return '';
+        }
+        $custommenu = new custom_menu($custommenuitems, current_language());
+        return $this->render($custommenu);
+    }
+
+    /*
+     * This renders the bootstrap top menu.
+     *
+     * This renderer is needed to enable the Bootstrap style navigation.
+     */
+    protected function render_custom_menu(custom_menu $menu) {
+        static $menucount = 0;
+        // If the menu has no children return an empty string
+        if (!$menu->has_children()) {
+            return '';
+        }
+        // Increment the menu count. This is used for ID's that get worked with
+        // in JavaScript as is essential
+        $menucount++;
+        // Initialise this custom menu (the custom menu object is contained in javascript-static
+        $jscode = js_writer::function_call_with_Y('M.core_custom_menu.init', array('custom_menu_'.$menucount));
+        $jscode = "(function(){{$jscode}})";
+        $this->page->requires->yui_module('node-menunav', $jscode);
+        // Build the root nodes as required by YUI
+        $content = html_writer::start_tag('div', array('id'=>'custom_menu_'.$menucount, 'class'=>'yui3-menu yui3-menu-horizontal javascript-disabled custom-menu'));
+        $content .= html_writer::start_tag('div', array('class'=>'yui3-menu-content'));
+        $content .= html_writer::start_tag('ul');
+        // Render each child
+        foreach ($menu->get_children() as $item) {
+            $content .= $this->render_custom_menu_item($item);
+        }
+        // Close the open tags
+        $content .= html_writer::end_tag('ul');
+        $content .= html_writer::end_tag('div');
+        $content .= html_writer::end_tag('div');
+        // Return the custom menu
+        return $content;
+    }
+
+    /**
+     * Renders tabtree
+     *
+     * @param tabtree $tabtree
+     * @return string
+     */
+    protected function render_tabtree(tabtree $tabtree) {
+        if (empty($tabtree->subtree)) {
+            return '';
+        }
+        $str = '';
+        $str .= html_writer::start_tag('div', array('class' => 'tabtree'));
+        $str .= $this->render_tabobject($tabtree);
+        $str .= html_writer::end_tag('div').
+                html_writer::tag('div', ' ', array('class' => 'clearer'));
+        return $str;
+    }
+
+    /**
+     * Renders tabobject (part of tabtree)
+     *
+     * This function is called from {@link core_renderer::render_tabtree()}
+     * and also it calls itself when printing the $tabobject subtree recursively.
+     *
+     * @param tabobject $tabobject
+     * @return string HTML fragment
+     */
+    protected function render_tabobject(tabobject $tab) {
+        throw new coding_exception('Tab objects should not be directly rendered.');
+    }
+
+    /**
+     * Prints a nice side block with an optional header.
+     *
+     * The content is described
+     * by a {@link core_renderer::block_contents} object.
+     *
+     * <div id="inst{$instanceid}" class="block_{$blockname} block">
+     *      <div class="header"></div>
+     *      <div class="content">
+     *          ...CONTENT...
+     *          <div class="footer">
+     *          </div>
+     *      </div>
+     *      <div class="annotation">
+     *      </div>
+     * </div>
+     *
+     * @param block_contents $bc HTML for the content
+     * @param string $region the region the block is appearing in.
+     * @return string the HTML to be output.
+     */
+    public function block(block_contents $bc, $region) {
+        $bc = clone($bc); // Avoid messing up the object passed in.
+        if (empty($bc->blockinstanceid) || !strip_tags($bc->title)) {
+            $bc->collapsible = block_contents::NOT_HIDEABLE;
+        }
+        if (!empty($bc->blockinstanceid)) {
+            $bc->attributes['data-instanceid'] = $bc->blockinstanceid;
+        }
+        $skiptitle = strip_tags($bc->title);
+        if ($bc->blockinstanceid && !empty($skiptitle)) {
+            $bc->attributes['aria-labelledby'] = 'instance-'.$bc->blockinstanceid.'-header';
+        } else if (!empty($bc->arialabel)) {
+            $bc->attributes['aria-label'] = $bc->arialabel;
+        }
+        if ($bc->dockable) {
+            $bc->attributes['data-dockable'] = 1;
+        }
+        if ($bc->collapsible == block_contents::HIDDEN) {
+            $bc->add_class('hidden');
+        }
+        if (!empty($bc->controls)) {
+            $bc->add_class('block_with_controls');
+        }
+
+
+        if (empty($skiptitle)) {
+            $output = '';
+            $skipdest = '';
+        } else {
+            $output = html_writer::link('#sb-'.$bc->skipid, get_string('skipa', 'access', $skiptitle),
+                    array('class' => 'skip skip-block', 'id' => 'fsb-' . $bc->skipid));
+            $skipdest = html_writer::span('', 'skip-block-to',
+                    array('id' => 'sb-' . $bc->skipid));
+        }
+
+        $output .= html_writer::start_tag('div', $bc->attributes);
+
+        $output .= $this->block_header($bc);
+        $output .= $this->block_content($bc);
+
+        $output .= html_writer::end_tag('div');
+
+        $output .= $this->block_annotation($bc);
+
+        $output .= $skipdest;
+
+        $this->init_block_hider_js($bc);
+        return $output;
+    }
+
+    /**
+     * Returns the CSS classes to apply to the body tag.
+     *
+     * @since Moodle 2.5.1 2.6
+     * @param array $additionalclasses Any additional classes to apply.
+     * @return string
+     */
+    public function body_css_classes(array $additionalclasses = array()) {
+        // Add a class for each block region on the page.
+        // We use the block manager here because the theme object makes get_string calls.
+        $usedregions = array();
+        foreach ($this->page->blocks->get_regions() as $region) {
+            $additionalclasses[] = 'has-region-'.$region;
+            if ($this->page->blocks->region_has_content($region, $this)) {
+                $additionalclasses[] = 'used-region-'.$region;
+                $usedregions[] = $region;
+            } else {
+                $additionalclasses[] = 'empty-region-'.$region;
+            }
+            if ($this->page->blocks->region_completely_docked($region, $this)) {
+                $additionalclasses[] = 'docked-region-'.$region;
+            }
+        }
+        if (!$usedregions) {
+            // No regions means there is only content, add 'content-only' class.
+            $additionalclasses[] = 'content-only';
+        } else if (count($usedregions) === 1) {
+            // Add the -only class for the only used region.
+            $region = array_shift($usedregions);
+            $additionalclasses[] = $region . '-only';
+        }
+        foreach ($this->page->layout_options as $option => $value) {
+            if ($value) {
+                $additionalclasses[] = 'layout-option-'.$option;
+            }
+        }
+        $css = $this->page->bodyclasses .' '. join(' ', $additionalclasses);
+        return $css;
+    }
+
+    /**
+     * Renders preferences groups.
+     *
+     * @param  preferences_groups $renderable The renderable
+     * @return string The output.
+     */
+    public function render_preferences_groups(preferences_groups $renderable) {
+        $html = '';
+        $html .= html_writer::start_div('row-fluid');
+        $html .= html_writer::start_tag('div', array('class' => 'span12 preferences-groups'));
+        $i = 0;
+        $open = false;
+        foreach ($renderable->groups as $group) {
+            if ($i == 0 || $i % 3 == 0) {
+                if ($open) {
+                    $html .= html_writer::end_tag('div');
+                }
+                $html .= html_writer::start_tag('div', array('class' => 'row-fluid'));
+                $open = true;
+            }
+            $html .= $this->render($group);
+            $i++;
+        }
+
+        $html .= html_writer::end_tag('div');
+
+        $html .= html_writer::end_tag('ul');
+        $html .= html_writer::end_tag('div');
+        $html .= html_writer::end_div();
+        return $html;
+    }
+
+    /**
+     * Renders an action menu component.
+     *
+     * ARIA references:
+     *   - http://www.w3.org/WAI/GL/wiki/Using_ARIA_menus
+     *   - http://stackoverflow.com/questions/12279113/recommended-wai-aria-implementation-for-navigation-bar-menu
+     *
+     * @param action_menu $menu
+     * @return string HTML
+     */
+    public function render_action_menu(action_menu $menu) {
+        $context = $menu->export_for_template($this);
+        return $this->render_from_template('core/action_menu', $context);
+    }
+
+    /**
+     * Implementation of user image rendering.
+     *
+     * @param help_icon $helpicon A help icon instance
+     * @return string HTML fragment
+     */
+    protected function render_help_icon(help_icon $helpicon) {
+        return $this->render_from_template('core/help_icon', $helpicon->export_for_template($this));
+    }
+
+    /**
+     * Renders a single button widget.
+     *
+     * This will return HTML to display a form containing a single button.
+     *
+     * @param single_button $button
+     * @return string HTML fragment
+     */
+    protected function render_single_button(single_button $button) {
+        $attributes = array('type'     => 'submit',
+                'value'    => $button->label,
+                'disabled' => $button->disabled ? 'disabled' : null,
+                'title'    => $button->tooltip);
+
+        if ($button->actions) {
+            $id = html_writer::random_id('single_button');
+            $attributes['id'] = $id;
+            foreach ($button->actions as $action) {
+                $this->add_action_handler($action, $id);
+            }
+        }
+
+        // first the input element
+        $output = html_writer::empty_tag('input', $attributes);
+
+        // then hidden fields
+        $params = $button->url->params();
+        if ($button->method === 'post') {
+            $params['sesskey'] = sesskey();
+        }
+        foreach ($params as $var => $val) {
+            $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => $var, 'value' => $val));
+        }
+
+        // then div wrapper for xhtml strictness
+        $output = html_writer::tag('div', $output);
+
+        // now the form itself around it
+        if ($button->method === 'get') {
+            $url = $button->url->out_omit_querystring(true); // url without params, the anchor part allowed
+        } else {
+            $url = $button->url->out_omit_querystring();     // url without params, the anchor part not allowed
+        }
+        if ($url === '') {
+            $url = '#'; // there has to be always some action
+        }
+        $attributes = array('method' => $button->method,
+                'action' => $url,
+                'id'     => $button->formid);
+        $output = html_writer::tag('form', $output, $attributes);
+
+        // and finally one more wrapper with class
+        return html_writer::tag('div', $output, array('class' => $button->class));
+    }
+
+    /**
+     * Renders the login form.
+     *
+     * @param \core_auth\output\login $form The renderable.
+     * @return string
+     */
+    public function render_login(\core_auth\output\login $form) {
+        global $CFG;
+
+        $context = $form->export_for_template($this);
+
+        // Override because rendering is not supported in template yet.
+        if ($CFG->rememberusername == 0) {
+            $context->cookieshelpiconformatted = $this->help_icon('cookiesenabledonlysession');
+        } else {
+            $context->cookieshelpiconformatted = $this->help_icon('cookiesenabled');
+        }
+        $context->errorformatted = $this->error_text($context->error);
+
+        return $this->render_from_template('core/loginform', $context);
+    }
+
+    /**
+     * Render the login signup form into a nice template for the theme.
+     *
+     * @param mform $form
+     * @return string
+     */
+    public function render_login_signup_form($form) {
+        $context = $form->export_for_template($this);
+
+        return $this->render_from_template('core/signup_form_layout', $context);
+    }
+
+}
index 1f90ef9..e856a42 100644 (file)
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-require_once('renderers/core_renderer.php');
-
+require_once($CFG->dirroot . '/theme/bootstrapbase/renderers/core_renderer.php');
+require_once($CFG->dirroot . '/theme/bootstrapbase/renderers/block_settings_renderer.php');
+require_once($CFG->dirroot . '/theme/bootstrapbase/renderers/gradereport_history_renderer.php');
+require_once($CFG->dirroot . '/theme/bootstrapbase/renderers/core/course_renderer.php');
+require_once($CFG->dirroot . '/theme/bootstrapbase/renderers/core/files_renderer.php');
+require_once($CFG->dirroot . '/theme/bootstrapbase/renderers/core_course/management/renderer.php');
+require_once($CFG->dirroot . '/theme/bootstrapbase/renderers/core_question/bank_renderer.php');
index 2fa7ae7..9e009d8 100644 (file)
@@ -77,6 +77,30 @@ class theme_bootstrapbase_core_renderer extends core_renderer {
                 $list_items . '</ul></nav>';
     }
 
+    /**
+     * This code renders the navbar button to control the display of the custom menu
+     * on smaller screens.
+     *
+     * Do not display the button if the menu is empty.
+     *
+     * @return string HTML fragment
+     */
+    protected function navbar_button() {
+        global $CFG;
+
+        if (empty($CFG->custommenuitems) && $this->lang_menu() == '') {
+            return '';
+        }
+
+        $iconbar = html_writer::tag('span', '', array('class' => 'icon-bar'));
+        $button = html_writer::tag('a', $iconbar . "\n" . $iconbar. "\n" . $iconbar, array(
+                'class'       => 'btn btn-navbar',
+                'data-toggle' => 'collapse',
+                'data-target' => '.nav-collapse'
+        ));
+        return $button;
+    }
+
     /*
      * Overriding the custom_menu function ensures the custom menu is
      * always shown, even if no menu items are configured in the global
@@ -187,30 +211,6 @@ class theme_bootstrapbase_core_renderer extends core_renderer {
         return $content;
     }
 
-    /**
-     * This code renders the navbar button to control the display of the custom menu
-     * on smaller screens.
-     *
-     * Do not display the button if the menu is empty.
-     *
-     * @return string HTML fragment
-     */
-    protected function navbar_button() {
-        global $CFG;
-
-        if (empty($CFG->custommenuitems) && $this->lang_menu() == '') {
-            return '';
-        }
-
-        $iconbar = html_writer::tag('span', '', array('class' => 'icon-bar'));
-        $button = html_writer::tag('a', $iconbar . "\n" . $iconbar. "\n" . $iconbar, array(
-            'class'       => 'btn btn-navbar',
-            'data-toggle' => 'collapse',
-            'data-target' => '.nav-collapse'
-        ));
-        return $button;
-    }
-
     /**
      * Renders tabtree
      *
@@ -256,6 +256,340 @@ class theme_bootstrapbase_core_renderer extends core_renderer {
             return html_writer::tag('li', $link, $params);
         }
     }
+
+    /**
+     * Wrapper for header elements.
+     *
+     * @return string HTML to display the main header.
+     */
+    public function full_header() {
+        $html = html_writer::start_tag('header', array('id' => 'page-header', 'class' => 'clearfix'));
+        $html .= $this->context_header();
+        $html .= html_writer::start_div('clearfix', array('id' => 'page-navbar'));
+        $html .= html_writer::tag('div', $this->navbar(), array('class' => 'breadcrumb-nav'));
+        $html .= html_writer::div($this->page_heading_button(), 'breadcrumb-button');
+        $html .= html_writer::end_div();
+        $html .= html_writer::tag('div', $this->course_header(), array('id' => 'course-header'));
+        $html .= html_writer::end_tag('header');
+        return $html;
+    }
+
+    /**
+     * Get the compact logo URL.
+     *
+     * @return string
+     */
+    public function get_compact_logo_url($maxwidth = 100, $maxheight = 100) {
+        return parent::get_compact_logo_url(null, 70);
+    }
+
+    /**
+     * Prints a nice side block with an optional header.
+     *
+     * The content is described
+     * by a {@link core_renderer::block_contents} object.
+     *
+     * <div id="inst{$instanceid}" class="block_{$blockname} block">
+     *      <div class="header"></div>
+     *      <div class="content">
+     *          ...CONTENT...
+     *          <div class="footer">
+     *          </div>
+     *      </div>
+     *      <div class="annotation">
+     *      </div>
+     * </div>
+     *
+     * @param block_contents $bc HTML for the content
+     * @param string $region the region the block is appearing in.
+     * @return string the HTML to be output.
+     */
+    public function block(block_contents $bc, $region) {
+        $bc = clone($bc); // Avoid messing up the object passed in.
+        if (empty($bc->blockinstanceid) || !strip_tags($bc->title)) {
+            $bc->collapsible = block_contents::NOT_HIDEABLE;
+        }
+        if (!empty($bc->blockinstanceid)) {
+            $bc->attributes['data-instanceid'] = $bc->blockinstanceid;
+        }
+        $skiptitle = strip_tags($bc->title);
+        if ($bc->blockinstanceid && !empty($skiptitle)) {
+            $bc->attributes['aria-labelledby'] = 'instance-'.$bc->blockinstanceid.'-header';
+        } else if (!empty($bc->arialabel)) {
+            $bc->attributes['aria-label'] = $bc->arialabel;
+        }
+        if ($bc->dockable) {
+            $bc->attributes['data-dockable'] = 1;
+        }
+        if ($bc->collapsible == block_contents::HIDDEN) {
+            $bc->add_class('hidden');
+        }
+        if (!empty($bc->controls)) {
+            $bc->add_class('block_with_controls');
+        }
+
+
+        if (empty($skiptitle)) {
+            $output = '';
+            $skipdest = '';
+        } else {
+            $output = html_writer::link('#sb-'.$bc->skipid, get_string('skipa', 'access', $skiptitle),
+                    array('class' => 'skip skip-block', 'id' => 'fsb-' . $bc->skipid));
+            $skipdest = html_writer::span('', 'skip-block-to',
+                    array('id' => 'sb-' . $bc->skipid));
+        }
+
+        $output .= html_writer::start_tag('div', $bc->attributes);
+
+        $output .= $this->block_header($bc);
+        $output .= $this->block_content($bc);
+
+        $output .= html_writer::end_tag('div');
+
+        $output .= $this->block_annotation($bc);
+
+        $output .= $skipdest;
+
+        $this->init_block_hider_js($bc);
+        return $output;
+    }
+
+    /**
+     * Produces a header for a block
+     *
+     * @param block_contents $bc
+     * @return string
+     */
+    protected function block_header(block_contents $bc) {
+
+        $title = '';
+        if ($bc->title) {
+            $attributes = array();
+            if ($bc->blockinstanceid) {
+                $attributes['id'] = 'instance-'.$bc->blockinstanceid.'-header';
+            }
+            $title = html_writer::tag('h2', $bc->title, $attributes);
+        }
+
+        $blockid = null;
+        if (isset($bc->attributes['id'])) {
+            $blockid = $bc->attributes['id'];
+        }
+        $controlshtml = $this->block_controls($bc->controls, $blockid);
+
+        $output = '';
+        if ($title || $controlshtml) {
+            $output .= html_writer::tag('div', html_writer::tag('div', html_writer::tag('div', '', array('class'=>'block_action')). $title . $controlshtml, array('class' => 'title')), array('class' => 'header'));
+        }
+        return $output;
+    }
+
+    /**
+     * Produces the content area for a block
+     *
+     * @param block_contents $bc
+     * @return string
+     */
+    protected function block_content(block_contents $bc) {
+        $output = html_writer::start_tag('div', array('class' => 'content'));
+        if (!$bc->title && !$this->block_controls($bc->controls)) {
+            $output .= html_writer::tag('div', '', array('class'=>'block_action notitle'));
+        }
+        $output .= $bc->content;
+        $output .= $this->block_footer($bc);
+        $output .= html_writer::end_tag('div');
+
+        return $output;
+    }
+
+    /**
+     * Produces the footer for a block
+     *
+     * @param block_contents $bc
+     * @return string
+     */
+    protected function block_footer(block_contents $bc) {
+        $output = '';
+        if ($bc->footer) {
+            $output .= html_writer::tag('div', $bc->footer, array('class' => 'footer'));
+        }
+        return $output;
+    }
+
+    /**
+     * Produces the annotation for a block
+     *
+     * @param block_contents $bc
+     * @return string
+     */
+    protected function block_annotation(block_contents $bc) {
+        $output = '';
+        if ($bc->annotation) {
+            $output .= html_writer::tag('div', $bc->annotation, array('class' => 'blockannotation'));
+        }
+        return $output;
+    }
+
+    /**
+     * Calls the JS require function to hide a block.
+     *
+     * @param block_contents $bc A block_contents object
+     */
+    protected function init_block_hider_js(block_contents $bc) {
+        if (!empty($bc->attributes['id']) and $bc->collapsible != block_contents::NOT_HIDEABLE) {
+            $config = new stdClass;
+            $config->id = $bc->attributes['id'];
+            $config->title = strip_tags($bc->title);
+            $config->preference = 'block' . $bc->blockinstanceid . 'hidden';
+            $config->tooltipVisible = get_string('hideblocka', 'access', $config->title);
+            $config->tooltipHidden = get_string('showblocka', 'access', $config->title);
+
+            $this->page->requires->js_init_call('M.util.init_block_hider', array($config));
+            user_preference_allow_ajax_update($config->preference, PARAM_BOOL);
+        }
+    }
+
+    /**
+     * Returns the CSS classes to apply to the body tag.
+     *
+     * @since Moodle 2.5.1 2.6
+     * @param array $additionalclasses Any additional classes to apply.
+     * @return string
+     */
+    public function body_css_classes(array $additionalclasses = array()) {
+        // Add a class for each block region on the page.
+        // We use the block manager here because the theme object makes get_string calls.
+        $usedregions = array();
+        foreach ($this->page->blocks->get_regions() as $region) {
+            $additionalclasses[] = 'has-region-'.$region;
+            if ($this->page->blocks->region_has_content($region, $this)) {
+                $additionalclasses[] = 'used-region-'.$region;
+                $usedregions[] = $region;
+            } else {
+                $additionalclasses[] = 'empty-region-'.$region;
+            }
+            if ($this->page->blocks->region_completely_docked($region, $this)) {
+                $additionalclasses[] = 'docked-region-'.$region;
+            }
+        }
+        if (!$usedregions) {
+            // No regions means there is only content, add 'content-only' class.
+            $additionalclasses[] = 'content-only';
+        } else if (count($usedregions) === 1) {
+            // Add the -only class for the only used region.
+            $region = array_shift($usedregions);
+            $additionalclasses[] = $region . '-only';
+        }
+        foreach ($this->page->layout_options as $option => $value) {
+            if ($value) {
+                $additionalclasses[] = 'layout-option-'.$option;
+            }
+        }
+        $css = $this->page->bodyclasses .' '. join(' ', $additionalclasses);
+        return $css;
+    }
+
+    /**
+     * Renders preferences groups.
+     *
+     * @param  preferences_groups $renderable The renderable
+     * @return string The output.
+     */
+    public function render_preferences_groups(preferences_groups $renderable) {
+        $html = '';
+        $html .= html_writer::start_div('row-fluid');
+        $html .= html_writer::start_tag('div', array('class' => 'span12 preferences-groups'));
+        $i = 0;
+        $open = false;
+        foreach ($renderable->groups as $group) {
+            if ($i == 0 || $i % 3 == 0) {
+                if ($open) {
+                    $html .= html_writer::end_tag('div');
+                }
+                $html .= html_writer::start_tag('div', array('class' => 'row-fluid'));
+                $open = true;
+            }
+            $html .= $this->render($group);
+            $i++;
+        }
+
+        $html .= html_writer::end_tag('div');
+
+        $html .= html_writer::end_tag('ul');
+        $html .= html_writer::end_tag('div');
+        $html .= html_writer::end_div();
+        return $html;
+    }
+
+    /**
+     * Renders an action menu component.
+     *
+     * ARIA references:
+     *   - http://www.w3.org/WAI/GL/wiki/Using_ARIA_menus
+     *   - http://stackoverflow.com/questions/12279113/recommended-wai-aria-implementation-for-navigation-bar-menu
+     *
+     * @param action_menu $menu
+     * @return string HTML
+     */
+    public function render_action_menu(action_menu $menu) {
+        $context = $menu->export_for_template($this);
+        return $this->render_from_template('core/action_menu', $context);
+    }
+
+    /**
+     * Renders a single button widget.
+     *
+     * This will return HTML to display a form containing a single button.
+     *
+     * @param single_button $button
+     * @return string HTML fragment
+     */
+    protected function render_single_button(single_button $button) {
+        $attributes = array('type'     => 'submit',
+                'value'    => $button->label,
+                'disabled' => $button->disabled ? 'disabled' : null,
+                'title'    => $button->tooltip);
+
+        if ($button->actions) {
+            $id = html_writer::random_id('single_button');
+            $attributes['id'] = $id;
+            foreach ($button->actions as $action) {
+                $this->add_action_handler($action, $id);
+            }
+        }
+
+        // first the input element
+        $output = html_writer::empty_tag('input', $attributes);
+
+        // then hidden fields
+        $params = $button->url->params();
+        if ($button->method === 'post') {
+            $params['sesskey'] = sesskey();
+        }
+        foreach ($params as $var => $val) {
+            $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => $var, 'value' => $val));
+        }
+
+        // then div wrapper for xhtml strictness
+        $output = html_writer::tag('div', $output);
+
+        // now the form itself around it
+        if ($button->method === 'get') {
+            $url = $button->url->out_omit_querystring(true); // url without params, the anchor part allowed
+        } else {
+            $url = $button->url->out_omit_querystring();     // url without params, the anchor part not allowed
+        }
+        if ($url === '') {
+            $url = '#'; // there has to be always some action
+        }
+        $attributes = array('method' => $button->method,
+                'action' => $url,
+                'id'     => $button->formid);
+        $output = html_writer::tag('form', $output, $attributes);
+
+        // and finally one more wrapper with class
+        return html_writer::tag('div', $output, array('class' => $button->class));
+    }
 }
 
 /**
index 595d3f6..9191059 100644 (file)
@@ -258,7 +258,7 @@ class behat_theme_bootstrapbase_behat_course extends behat_course {
     public function i_navigate_to_course_participants() {
         $coursestr = behat_context_helper::escape(get_string('courses'));
         $mycoursestr = behat_context_helper::escape(get_string('mycourses'));
-        $xpath = "//div[contains(@class,'block')]//li[p/*[string(.)=$coursestr or string(.)=$mycoursestr]]";
+        $xpath = "//section[contains(@class,'block')]//li[p/*[string(.)=$coursestr or string(.)=$mycoursestr]]";
         $this->execute('behat_general::i_click_on_in_the', [get_string('participants'), 'link', $xpath, 'xpath_element']);
     }
 }
index 6e7e6a5..30388fe 100644 (file)
@@ -96,7 +96,7 @@ class behat_theme_bootstrapbase_behat_navigation extends behat_navigation {
     public function should_exist_in_current_page_administration($element, $selectortype) {
         $parentnodes = array_map('trim', explode('>', $element));
         // Find the name of the first category of the administration block tree.
-        $xpath = '//div[contains(@class,\'block_settings\')]//div[@id=\'settingsnav\']/ul/li[1]/p[1]/span';
+        $xpath = '//section[contains(@class,\'block_settings\')]//div[@id=\'settingsnav\']/ul/li[1]/p[1]/span';
         $node = $this->find('xpath', $xpath);
         array_unshift($parentnodes, $node->getText());
         $lastnode = array_pop($parentnodes);
@@ -110,7 +110,7 @@ class behat_theme_bootstrapbase_behat_navigation extends behat_navigation {
     public function should_not_exist_in_current_page_administration($element, $selectortype) {
         $parentnodes = array_map('trim', explode('>', $element));
         // Find the name of the first category of the administration block tree.
-        $xpath = '//div[contains(@class,\'block_settings\')]//div[@id=\'settingsnav\']/ul/li[1]/p[1]/span';
+        $xpath = '//section[contains(@class,\'block_settings\')]//div[@id=\'settingsnav\']/ul/li[1]/p[1]/span';
         $node = $this->find('xpath', $xpath);
         array_unshift($parentnodes, $node->getText());
         $lastnode = array_pop($parentnodes);
@@ -124,7 +124,7 @@ class behat_theme_bootstrapbase_behat_navigation extends behat_navigation {
     public function i_navigate_to_in_current_page_administration($nodetext) {
         $parentnodes = array_map('trim', explode('>', $nodetext));
         // Find the name of the first category of the administration block tree.
-        $xpath = '//div[contains(@class,\'block_settings\')]//div[@id=\'settingsnav\']/ul/li[1]/p[1]/span';
+        $xpath = '//section[contains(@class,\'block_settings\')]//div[@id=\'settingsnav\']/ul/li[1]/p[1]/span';
         $node = $this->find('xpath', $xpath);
         array_unshift($parentnodes, $node->getText());
         $lastnode = array_pop($parentnodes);