MDL-55407 theme_noname: Remove styling and JS from blocks
[moodle.git] / theme / noname / classes / output / core_renderer.php
CommitLineData
536f0460
DW
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17namespace theme_noname\output;
18
19use html_writer;
20use tabobject;
21use tabtree;
22use custom_menu_item;
23use custom_menu;
d7fbf722
DW
24use block_contents;
25use stdClass;
536f0460
DW
26
27defined('MOODLE_INTERNAL') || die;
28
29/**
30 * Renderers to align Moodle's HTML with that expected by Bootstrap
31 *
32 * @package theme_noname
33 * @copyright 2012 Bas Brands, www.basbrands.nl
34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35 */
36
37class core_renderer extends \core_renderer {
38
39 /** @var custom_menu_item language The language menu if created */
40 protected $language = null;
41
42 /**
43 * The standard tags that should be included in the <head> tag
44 * including a meta description for the front page
45 *
46 * @return string HTML fragment.
47 */
48 public function standard_head_html() {
49 global $SITE, $PAGE;
50
51 $output = parent::standard_head_html();
52 if ($PAGE->pagelayout == 'frontpage') {
53 $summary = s(strip_tags(format_text($SITE->summary, FORMAT_HTML)));
54 if (!empty($summary)) {
55 $output .= "<meta name=\"description\" content=\"$summary\" />\n";
56 }
57 }
58
59 return $output;
60 }
61
62 /*
63 * This renders the navbar.
64 * Uses bootstrap compatible html.
65 */
66 public function navbar() {
67 $items = $this->page->navbar->get_items();
68 if (empty($items)) {
69 return '';
70 }
71
72 $breadcrumbs = array();
73 foreach ($items as $item) {
74 $item->hideicon = true;
75 $breadcrumbs[] = $this->render($item);
76 }
77 $list_items = '<li>'.join(" </li><li>", $breadcrumbs).'</li>';
78 $title = '<span class="accesshide" id="navbar-label">'.get_string('pagepath').'</span>';
79 return $title . '<nav aria-labelledby="navbar-label"><ul class="breadcrumb">' .
80 $list_items . '</ul></nav>';
81 }
82
83 /*
84 * Overriding the custom_menu function ensures the custom menu is
85 * always shown, even if no menu items are configured in the global
86 * theme settings page.
87 */
88 public function custom_menu($custommenuitems = '') {
89 global $CFG;
90
91 if (empty($custommenuitems) && !empty($CFG->custommenuitems)) {
92 $custommenuitems = $CFG->custommenuitems;
93 }
94 $custommenu = new custom_menu($custommenuitems, current_language());
95 return $this->render_custom_menu($custommenu);
96 }
97
98 /*
99 * This renders the bootstrap top menu.
100 *
101 * This renderer is needed to enable the Bootstrap style navigation.
102 */
103 protected function render_custom_menu(custom_menu $menu) {
104 global $CFG;
105
106 $langs = get_string_manager()->get_list_of_translations();
107 $haslangmenu = $this->lang_menu() != '';
108
109 if (!$menu->has_children() && !$haslangmenu) {
110 return '';
111 }
112
113 if ($haslangmenu) {
114 $strlang = get_string('language');
115 $currentlang = current_language();
116 if (isset($langs[$currentlang])) {
117 $currentlang = $langs[$currentlang];
118 } else {
119 $currentlang = $strlang;
120 }
121 $this->language = $menu->add($currentlang, new moodle_url('#'), $strlang, 10000);
122 foreach ($langs as $langtype => $langname) {
123 $this->language->add($langname, new moodle_url($this->page->url, array('lang' => $langtype)), $langname);
124 }
125 }
126
127 $content = '<ul class="nav">';
128 foreach ($menu->get_children() as $item) {
129 $content .= $this->render_custom_menu_item($item, 1);
130 }
131
132 return $content.'</ul>';
133 }
134
135 /*
136 * This code renders the custom menu items for the
137 * bootstrap dropdown menu.
138 */
139 protected function render_custom_menu_item(custom_menu_item $menunode, $level = 0 ) {
140 static $submenucount = 0;
141
142 $content = '';
143 if ($menunode->has_children()) {
144
145 if ($level == 1) {
146 $class = 'dropdown';
147 } else {
148 $class = 'dropdown-submenu';
149 }
150
151 if ($menunode === $this->language) {
152 $class .= ' langmenu';
153 }
154 $content = html_writer::start_tag('li', array('class' => $class));
155 // If the child has menus render it as a sub menu.
156 $submenucount++;
157 if ($menunode->get_url() !== null) {
158 $url = $menunode->get_url();
159 } else {
160 $url = '#cm_submenu_'.$submenucount;
161 }
162 $content .= html_writer::start_tag('a', array('href'=>$url, 'class'=>'dropdown-toggle', 'data-toggle'=>'dropdown', 'title'=>$menunode->get_title()));
163 $content .= $menunode->get_text();
164 if ($level == 1) {
165 $content .= '<b class="caret"></b>';
166 }
167 $content .= '</a>';
168 $content .= '<ul class="dropdown-menu">';
169 foreach ($menunode->get_children() as $menunode) {
170 $content .= $this->render_custom_menu_item($menunode, 0);
171 }
172 $content .= '</ul>';
173 } else {
174 // The node doesn't have children so produce a final menuitem.
175 // Also, if the node's text matches '####', add a class so we can treat it as a divider.
176 if (preg_match("/^#+$/", $menunode->get_text())) {
177 // This is a divider.
178 $content = '<li class="divider">&nbsp;</li>';
179 } else {
180 $content = '<li>';
181 if ($menunode->get_url() !== null) {
182 $url = $menunode->get_url();
183 } else {
184 $url = '#';
185 }
186 $content .= html_writer::link($url, $menunode->get_text(), array('title' => $menunode->get_title()));
187 $content .= '</li>';
188 }
189 }
190 return $content;
191 }
192
193 /**
194 * This code renders the navbar button to control the display of the custom menu
195 * on smaller screens.
196 *
197 * Do not display the button if the menu is empty.
198 *
199 * @return string HTML fragment
200 */
201 public function navbar_button() {
202 global $CFG;
203
204 if (empty($CFG->custommenuitems) && $this->lang_menu() == '') {
205 return '';
206 }
207
208 $iconbar = html_writer::tag('span', '', array('class' => 'icon-bar'));
209 $button = html_writer::tag('a', $iconbar . "\n" . $iconbar. "\n" . $iconbar, array(
210 'class' => 'btn btn-navbar',
211 'data-toggle' => 'collapse',
212 'data-target' => '.nav-collapse'
213 ));
214 return $button;
215 }
216
217 /**
218 * Renders tabtree
219 *
220 * @param tabtree $tabtree
221 * @return string
222 */
223 protected function render_tabtree(tabtree $tabtree) {
224 if (empty($tabtree->subtree)) {
225 return '';
226 }
227 $firstrow = $secondrow = '';
228 foreach ($tabtree->subtree as $tab) {
229 $firstrow .= $this->render($tab);
230 if (($tab->selected || $tab->activated) && !empty($tab->subtree) && $tab->subtree !== array()) {
231 $secondrow = $this->tabtree($tab->subtree);
232 }
233 }
234 return html_writer::tag('ul', $firstrow, array('class' => 'nav nav-tabs')) . $secondrow;
235 }
236
237 /**
238 * Renders tabobject (part of tabtree)
239 *
240 * This function is called from {@link core_renderer::render_tabtree()}
241 * and also it calls itself when printing the $tabobject subtree recursively.
242 *
243 * @param tabobject $tabobject
244 * @return string HTML fragment
245 */
246 protected function render_tabobject(tabobject $tab) {
247 if (($tab->selected and (!$tab->linkedwhenselected)) or $tab->activated) {
248 return html_writer::tag('li', html_writer::tag('a', $tab->text), array('class' => 'active'));
249 } else if ($tab->inactive) {
250 return html_writer::tag('li', html_writer::tag('a', $tab->text), array('class' => 'disabled'));
251 } else {
252 if (!($tab->link instanceof moodle_url)) {
253 // backward compartibility when link was passed as quoted string
254 $link = "<a href=\"$tab->link\" title=\"$tab->title\">$tab->text</a>";
255 } else {
256 $link = html_writer::link($tab->link, $tab->text, array('title' => $tab->title));
257 }
258 $params = $tab->selected ? array('class' => 'active') : null;
259 return html_writer::tag('li', $link, $params);
260 }
261 }
d7fbf722
DW
262
263 /**
264 * Prints a nice side block with an optional header.
265 *
266 * @param block_contents $bc HTML for the content
267 * @param string $region the region the block is appearing in.
268 * @return string the HTML to be output.
269 */
270 public function block(block_contents $bc, $region) {
271 $bc = clone($bc); // Avoid messing up the object passed in.
272 if (empty($bc->blockinstanceid) || !strip_tags($bc->title)) {
273 $bc->collapsible = block_contents::NOT_HIDEABLE;
274 }
275 if (!empty($bc->blockinstanceid)) {
276 $bc->attributes['data-instanceid'] = $bc->blockinstanceid;
277 }
278 $skiptitle = strip_tags($bc->title);
279 if ($bc->blockinstanceid && !empty($skiptitle)) {
280 $bc->attributes['aria-labelledby'] = 'instance-'.$bc->blockinstanceid.'-header';
281 } else if (!empty($bc->arialabel)) {
282 $bc->attributes['aria-label'] = $bc->arialabel;
283 }
284 if ($bc->dockable) {
285 $bc->attributes['data-dockable'] = 1;
286 }
287 if ($bc->collapsible == block_contents::HIDDEN) {
288 $bc->add_class('hidden');
289 }
290 if (!empty($bc->controls)) {
291 $bc->add_class('block_with_controls');
292 }
293
294 $id = !empty($bc->attributes['id']) ? $bc->attributes['id'] : uniqid('block-');
295 $context = new stdClass();
296 $context->skipid = $bc->skipid;
297 $context->blockinstanceid = $bc->blockinstanceid;
298 $context->dockable = $bc->dockable;
299 $context->id = $id;
300 $context->hidden = $bc->collapsible == block_contents::HIDDEN;
301 $context->skiptitle = strip_tags($bc->title);
302 $context->showskiplink = !empty($context->skiptitle);
303 $context->arialabel = $bc->arialabel;
304 $context->ariarole = !empty($bc->attributes['role']) ? $bc->attributes['role'] : 'complementary';
305 $context->type = $bc->attributes['data-block'];
306 $context->title = $bc->title;
307 $context->content = $bc->content;
308 $context->annotation = $bc->annotation;
309 $context->footer = $bc->footer;
310 $context->hascontrols = !empty($bc->controls);
311 if ($context->hascontrols) {
312 $context->controls = $this->block_controls($bc->controls, $id);
313 }
314
315 return $this->render_from_template('core/block', $context);
316 }
317
318 /**
319 * Returns the CSS classes to apply to the body tag.
320 *
321 * @since Moodle 2.5.1 2.6
322 * @param array $additionalclasses Any additional classes to apply.
323 * @return string
324 */
325 public function body_css_classes(array $additionalclasses = array()) {
326 return $this->page->bodyclasses;
327 }
536f0460 328}