MDL-30274 Correct typo of loginpage variable
[moodle.git] / theme / mymobile / renderers.php
CommitLineData
2fd7abbb 1<?php
3c0c2bf0 2// This file is part of Moodle - http://moodle.org/
2fd7abbb 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
17/**
3c0c2bf0 18 * Renderers for the mymobile theme
2fd7abbb 19 *
20 * @package theme
21 * @subpackage mymobile
22 * @copyright John Stabinger
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
3c0c2bf0
SH
25
26/**
27 * A custom renderer for the mymobile theme to produce snippets of content.
28 *
29 * @package theme
30 * @subpackage mymobile
31 * @copyright John Stabinger
32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33 */
34class theme_mymobile_renderer extends plugin_renderer_base {
35
36 /**
37 * Produces the settings tree
38 *
39 * @param settings_navigation $navigation
40 * @return string
41 */
42 public function settings_tree(settings_navigation $navigation) {
43 $content = $this->navigation_node($navigation, array('class' => 'settings'));
44 if (has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) {
45 // TODO: Work out whether something is missing from here.
46 }
47 return $content;
2fd7abbb 48 }
3c0c2bf0
SH
49
50 /**
51 * Produces the navigation tree
52 *
53 * @param global_navigation $navigation
54 * @return string
55 */
56 public function navigation_tree(global_navigation $navigation) {
57 return $this->navigation_node($navigation, array());
2fd7abbb 58 }
59
3c0c2bf0
SH
60 /**
61 * Protected method to render a navigaiton node
62 *
63 * @param navigation_node $node
64 * @param array $attrs
65 * @return type
66 */
67 protected function navigation_node(navigation_node $node, $attrs = array()) {
68 $items = $node->children;
69
70 // exit if empty, we don't want an empty ul element
71 if ($items->count() == 0) {
72 return '';
73 }
74
75 // array of nested li elements
76 $lis = array();
77 foreach ($items as $item) {
78 if (!$item->display) {
79 continue;
80 }
81
82 $isbranch = ($item->children->count() > 0 || $item->nodetype == navigation_node::NODETYPE_BRANCH);
83 $item->hideicon = true;
84
85 $content = $this->output->render($item);
86 $content .= $this->navigation_node($item);
87
88 if ($isbranch && !(is_string($item->action) || empty($item->action))) {
89 $content = html_writer::tag('li', $content, array('data-role' => 'list-divider', 'class' => (string)$item->key));
90 } else if($isbranch) {
91 $content = html_writer::tag('li', $content, array('data-role' => 'list-divider'));
92 } else {
93 $content = html_writer::tag('li', $content, array('class' => (string)$item->text));
94 }
95 $lis[] = $content;
96 }
97 if (!count($lis)) {
98 return '';
99 }
100 return implode("\n", $lis);
2fd7abbb 101 }
2fd7abbb 102}
2fd7abbb 103
3c0c2bf0
SH
104/**
105 * Overridden core renderer for the mymobile theme
106 *
107 * @package theme
108 * @subpackage mymobile
109 * @copyright John Stabinger
110 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
111 */
112class theme_mymobile_core_renderer extends core_renderer {
113
114 /**
115 * Returns the dtheme to use for the selected swatch
cf2de1cf 116 *
3c0c2bf0
SH
117 * @return string
118 */
119 protected function theme_swatch() {
120 $showswatch = 'light';
121 if (!empty($this->page->theme->settings->colourswatch)) {
122 $showswatch = $this->page->theme->settings->colourswatch;
2fd7abbb 123 }
124 if ($showswatch == 'light') {
3c0c2bf0
SH
125 $dtheme = 'b';
126 } else {
127 $dtheme = 'd';
128 }
129 return $dtheme;
130 }
131
132 /**
133 * Produces a heading
134 *
135 * @param string $text
136 * @param int $level
137 * @param string $classes
138 * @param string $id
139 * @return string
140 */
141 public function heading($text, $level = 2, $classes = 'main', $id = null) {
142 if ($classes == 'helpheading') {
143 // Keeps wrap from help headings in dialog.
144 $content = parent::heading($text, $level, $classes, $id);
145 } else {
146 $content = html_writer::start_tag('div', array('class' => 'headingwrap ui-bar-'.$this->theme_swatch() .' ui-footer'));
147 $content .= parent::heading($text, $level, $classes.' ui-title', $id);
148 $content .= html_writer::end_tag('div');
2fd7abbb 149 }
3c0c2bf0
SH
150 return $content;
151 }
2fd7abbb 152
3c0c2bf0
SH
153 /**
154 * Renders a block
155 *
156 * @param block_contents $bc
157 * @param string $region
158 * @return string
159 */
160 public function block(block_contents $bc, $region) {
161 // Avoid messing up the object passed in.
162 $bc = clone($bc);
163 // The mymobile theme does not support collapsible blocks.
164 $bc->collapsible = block_contents::NOT_HIDEABLE;
165 // There are no controls that are usable within the
166 $bc->controls = array();
167
168 // TODO: Do we still need to support accessibility here? Surely screen
169 // readers don't present themselves as mobile devices too often.
2fd7abbb 170 $skiptitle = strip_tags($bc->title);
171 if (empty($skiptitle)) {
172 $output = '';
173 $skipdest = '';
174 } else {
175 $output = html_writer::tag('a', get_string('skipa', 'access', $skiptitle), array('href' => '#sb-' . $bc->skipid, 'class' => 'skip-block'));
176 $skipdest = html_writer::tag('span', '', array('id' => 'sb-' . $bc->skipid, 'class' => 'skip-block-to'));
177 }
178 $testb = $bc->attributes['class'];
3c0c2bf0
SH
179
180 // TODO: Find a better solution to this hardcoded block checks
2fd7abbb 181 if ($testb == "block_calendar_month2 block") {
3c0c2bf0
SH
182 $output = html_writer::start_tag('span');
183 } else if ($testb == "block_course_overview block") {
184 $output = html_writer::start_tag('div');
185 } else {
186 if (!empty($this->page->theme->settings->colourswatch)) {
187 $showswatch = $this->page->theme->settings->colourswatch;
188 } else {
189 $showswatch = '';
190 }
191 if ($showswatch == 'light') {
192 $dtheme = 'd';
193 } else {
194 $dtheme = 'c';
195 }
196 $output = html_writer::start_tag('div', array('data-role' => 'collapsible', 'data-collapsed' => 'true', 'data-content-theme' => $dtheme));
2fd7abbb 197 }
3c0c2bf0
SH
198
199 $output .= html_writer::tag('h1', $this->block_header($bc));
2fd7abbb 200 $output .= html_writer::start_tag('div', $bc->attributes);
201 $output .= $this->block_content($bc);
2fd7abbb 202 $output .= html_writer::end_tag('div');
203 $output .= html_writer::end_tag('div');
204
205 $output .= $this->block_annotation($bc);
206
207 $output .= $skipdest;
208
209 return $output;
210 }
211
3c0c2bf0
SH
212 /**
213 * Produces a blocks header
214 *
215 * @param block_contents $bc
216 * @return string
217 */
2fd7abbb 218 protected function block_header(block_contents $bc) {
2fd7abbb 219 $title = '';
3c0c2bf0
SH
220 if (!$bc->title) {
221 return '&nbsp;';
2fd7abbb 222 }
3c0c2bf0
SH
223 $output = html_writer::start_tag('div', array('class' => 'header'));
224 $output .= html_writer::tag('div', html_writer::tag('div', '', array('class'=>'block_action')). $bc->title, array('class' => 'title'));
225 $output .= html_writer::end_tag('div');
2fd7abbb 226 return $output;
227 }
228
3c0c2bf0
SH
229 /**
230 * An evil function we don't want to execute
231 *
232 * @param block_contents $bc
233 */
234 protected function init_block_hider_js(block_contents $bc) {
235 // The mymobile theme in no shape or form supports the hiding of blocks
236 // this function has been defined and left empty intentionally so that
237 // the block hider JS is not even included.
2fd7abbb 238 }
2fd7abbb 239
3c0c2bf0
SH
240 /**
241 * Produces the navigation bar for the mymobile theme
242 *
243 * @return string
244 */
245 public function navbar() {
246 $items = $this->page->navbar->get_items();
2fd7abbb 247
3c0c2bf0 248 $htmlblocks = array(html_writer::tag('option', get_string('navigation'), array('data-placeholder' => 'true', 'value' => '-1')));
2fd7abbb 249 // Iterate the navarray and display each node
250 $itemcount = count($items);
251 $separator = "";
3c0c2bf0
SH
252
253 for ($i = 0; $i < $itemcount; $i++) {
2fd7abbb 254 $item = $items[$i];
255 $item->hideicon = true;
3c0c2bf0
SH
256 if ($i === 0) {
257 $content = html_writer::tag('option', $this->render($item), array('value' => (string)$item->action));
258 } else if (!empty($item->action)) {
259 $content = html_writer::tag('option', $this->render($item), array('value' => (string)$item->action));
2fd7abbb 260 } else {
3c0c2bf0 261 $content = '';
2fd7abbb 262 }
263 $htmlblocks[] = $content;
264 }
265
3c0c2bf0
SH
266 $navbarcontent = html_writer::start_tag('form', array('id' => 'navselectform'));
267 $navbarcontent .= html_writer::start_tag('select', array('id' => 'navselect', 'data-theme' => 'c', 'data-inline' => 'false', 'data-icon' => 'false'));
268 $navbarcontent .= join('', $htmlblocks);
269 $navbarcontent .= html_writer::end_tag('select');
270 $navbarcontent .= html_writer::end_tag('form');
2fd7abbb 271 // XHTML
272 return $navbarcontent;
3c0c2bf0 273 }
2fd7abbb 274
3c0c2bf0
SH
275 /**
276 * Renders a navigation node
277 *
278 * This function has been overridden to remove tabindexs
279 *
280 * @param navigation_node $item
281 * @return string
282 */
283 protected function render_navigation_node(navigation_node $item) {
284 // Generate the content normally
285 $content = parent::render_navigation_node($item);
286 // Strip out any tabindex's
287 $content = str_replace(' tabindex="0"', '', $content);
288 $content = str_replace(' tabindex=\'0\'', '', $content);
289 // Return the cleaned content
2fd7abbb 290 return $content;
291 }
292
3c0c2bf0
SH
293 /**
294 * Displays login info
295 *
296 * @return string
297 */
298 public function login_info() {
2fd7abbb 299 global $USER, $CFG, $DB, $SESSION;
300
301 if (during_initial_install()) {
302 return '';
303 }
304
305 $course = $this->page->course;
306
307 if (session_is_loggedinas()) {
308 $realuser = session_get_realuser();
309 $fullname = fullname($realuser, true);
2fd7abbb 310 $realuserinfo = " [<a href=\"$CFG->wwwroot/course/loginas.php?id=$course->id&amp;sesskey=".sesskey()."\">$fullname</a>] ";
311 } else {
312 $realuserinfo = '';
313 }
314
315 $loginurl = get_login_url();
316
317 if (empty($course->id)) {
318 // $course->id is not defined during installation
319 return '';
320 } else if (isloggedin()) {
321 $context = get_context_instance(CONTEXT_COURSE, $course->id);
2fd7abbb 322 $fullname = fullname($USER, true);
3c0c2bf0 323
2fd7abbb 324 // Since Moodle 2.0 this link always goes to the public profile page (not the course profile page)
3c0c2bf0
SH
325 // TODO: Test what happens when someone is using this via mnet [for this as well as login_info_footer]
326 // TODO: Test what happens when you use the loginas feature [for this as well as login_info_footer]
327 $username = "";
2fd7abbb 328 if (is_mnet_remote_user($USER) and $idprovider = $DB->get_record('mnet_host', array('id'=>$USER->mnethostid))) {
329 $username .= " from <a href=\"{$idprovider->wwwroot}\">{$idprovider->name}</a>";
330 }
331 if (isguestuser()) {
3c0c2bf0 332 $loggedinas = $realuserinfo.get_string('loggedinasguest')." (<a href=\"$loginurl\">".get_string('login').'</a>)';
2fd7abbb 333 } else if (is_role_switched($course->id)) { // Has switched roles
334 $rolename = '';
335 if ($role = $DB->get_record('role', array('id'=>$USER->access['rsw'][$context->path]))) {
336 $rolename = ': '.format_string($role->name);
337 }
2fd7abbb 338 } else {
3c0c2bf0 339 $loggedinas = $realuserinfo.$username.' <a id="mypower" data-inline="true" data-role="button" data-icon="mypower" data-ajax="false" class="ui-btn-right mypower" href="'.$CFG->wwwroot.'/login/logout.php?sesskey='.sesskey().'\">'.get_string('logout').'</a>';
2fd7abbb 340 }
341 } else {
3c0c2bf0 342 $loggedinas = '<a data-role="button" data-icon="alert" class="ui-btn-right nolog" href="'.$loginurl.'" data-prefetch>'.get_string('login').'</a>';
2fd7abbb 343 }
344
3c0c2bf0
SH
345 // TODO: Enable $CFG->displayloginfailures and test as admin what happens after you succesfully
346 // log in after a failed log in attempt. [for this as well as login_info_footer]
347 // This is probably totally unneeded
2fd7abbb 348 if (isset($SESSION->justloggedin)) {
349 unset($SESSION->justloggedin);
350 if (!empty($CFG->displayloginfailures)) {
351 if (!isguestuser()) {
352 if ($count = count_login_failures($CFG->displayloginfailures, $USER->username, $USER->lastlogin)) {
353 $loggedinas .= '&nbsp;<div class="loginfailures">';
354 if (empty($count->accounts)) {
355 $loggedinas .= get_string('failedloginattempts', '', $count);
356 } else {
357 $loggedinas .= get_string('failedloginattemptsall', '', $count);
358 }
359 if (has_capability('coursereport/log:view', get_context_instance(CONTEXT_SYSTEM))) {
3c0c2bf0 360 $loggedinas .= ' (<a href="'.$CFG->wwwroot.'/course/report/log/index.php?chooselog=1&amp;id=1&amp;modid=site_errors">'.get_string('logs').'</a>)';
2fd7abbb 361 }
362 $loggedinas .= '</div>';
363 }
364 }
365 }
366 }
367
368 return $loggedinas;
369 }
370
3c0c2bf0
SH
371 /**
372 * Displays login info in the footer
373 *
374 * @return string
375 */
376 public function login_info_footer() {
2fd7abbb 377 global $USER, $CFG, $DB, $SESSION;
378
379 if (during_initial_install()) {
380 return '';
381 }
382
4a645a68 383 $loginpage = ((string)$this->page->url === get_login_url());
2fd7abbb 384 $course = $this->page->course;
385
386 if (session_is_loggedinas()) {
387 $realuser = session_get_realuser();
388 $fullname = fullname($realuser, true);
389 $realuserinfo = ' [<a href="'.$CFG->wwwroot.'/course/loginas.php?id=$course->id&amp;sesskey='.sesskey().'">$fullname</a>] ';
390 } else {
391 $realuserinfo = '';
392 }
393
394 $loginurl = get_login_url();
395
396 if (empty($course->id)) {
397 // $course->id is not defined during installation
398 return '';
399 } else if (isloggedin()) {
400 $context = get_context_instance(CONTEXT_COURSE, $course->id);
401
402 $fullname = fullname($USER, true);
403 // Since Moodle 2.0 this link always goes to the public profile page (not the course profile page)
404 $username = '<a href="'.$CFG->wwwroot.'/user/profile.php?id='.$USER->id.'">'.$fullname.'</a>';
405 if (is_mnet_remote_user($USER) and $idprovider = $DB->get_record('mnet_host', array('id'=>$USER->mnethostid))) {
406 $username .= " from <a href=\"{$idprovider->wwwroot}\">{$idprovider->name}</a>";
407 }
408 if (isguestuser()) {
409 $loggedinas = $realuserinfo.get_string('loggedinasguest');
4a645a68 410 if (!$loginpage) {
2fd7abbb 411 $loggedinas .= " (<a href=\"$loginurl\">".get_string('login').'</a>)';
412 }
413 } else if (is_role_switched($course->id)) { // Has switched roles
414 $rolename = '';
415 if ($role = $DB->get_record('role', array('id'=>$USER->access['rsw'][$context->path]))) {
416 $rolename = ': '.format_string($role->name);
417 }
3c0c2bf0 418 $loggedinas = get_string('loggedinas', 'moodle', $username).$rolename." (<a href=\"$CFG->wwwroot/course/view.php?id=$course->id&amp;switchrole=0&amp;sesskey=".sesskey()."\">".get_string('switchrolereturn').'</a>)';
2fd7abbb 419 } else {
3c0c2bf0 420 $loggedinas = $realuserinfo.get_string('loggedinas', 'moodle', $username).' '." (<a href=\"$CFG->wwwroot/login/logout.php?sesskey=".sesskey()."\" data-ajax=\"false\">".get_string('logout').'</a>)';
2fd7abbb 421 }
422 } else {
423 $loggedinas = get_string('loggedinnot', 'moodle');
4a645a68 424 if (!$loginpage) {
2fd7abbb 425 $loggedinas .= " (<a href=\"$loginurl\">".get_string('login').'</a>)';
426 }
427 }
428
429 $loggedinas = '<div class="logininfo">'.$loggedinas.'</div>';
430
431 if (isset($SESSION->justloggedin)) {
432 unset($SESSION->justloggedin);
433 if (!empty($CFG->displayloginfailures)) {
434 if (!isguestuser()) {
435 if ($count = count_login_failures($CFG->displayloginfailures, $USER->username, $USER->lastlogin)) {
436 $loggedinas .= '&nbsp;<div class="loginfailures">';
437 if (empty($count->accounts)) {
438 $loggedinas .= get_string('failedloginattempts', '', $count);
439 } else {
440 $loggedinas .= get_string('failedloginattemptsall', '', $count);
441 }
442 if (has_capability('coursereport/log:view', get_context_instance(CONTEXT_SYSTEM))) {
3c0c2bf0 443 $loggedinas .= ' (<a href="'.$CFG->wwwroot.'/course/report/log/index.php?chooselog=1&amp;id=1&amp;modid=site_errors">'.get_string('logs').'</a>)';
2fd7abbb 444 }
445 $loggedinas .= '</div>';
446 }
447 }
448 }
449 }
450
451 return $loggedinas;
452 }
453
3c0c2bf0
SH
454 /**
455 * Prints a message and redirects
456 *
457 * @param string $encodedurl
458 * @param string $message
459 * @param int $delay
460 * @param true $debugdisableredirect
461 * @return type
462 */
463 public function redirect_message($encodedurl, $message, $delay, $debugdisableredirect) {
2fd7abbb 464 global $CFG;
465 $url = str_replace('&amp;', '&', $encodedurl);
3c0c2bf0
SH
466 // TODO: Find a much better solution for this... looks like it is just removing
467 // the anchor from the link.
468 // The below to fix redirect issues with ajax... John
2fd7abbb 469 $encodedurl = str_replace('#', '&', $encodedurl);
3c0c2bf0 470
2fd7abbb 471 switch ($this->page->state) {
472 case moodle_page::STATE_BEFORE_HEADER :
473 // No output yet it is safe to delivery the full arsenal of redirect methods
474 if (!$debugdisableredirect) {
475 // Don't use exactly the same time here, it can cause problems when both redirects fire at the same time.
476 $this->metarefreshtag = '<meta http-equiv="refresh" content="'. $delay .'; url='. $encodedurl .'" />'."\n";
2fd7abbb 477 }
478 $output = $this->header();
479 break;
480 case moodle_page::STATE_PRINTING_HEADER :
481 // We should hopefully never get here
482 throw new coding_exception('You cannot redirect while printing the page header');
483 break;
484 case moodle_page::STATE_IN_BODY :
485 // We really shouldn't be here but we can deal with this
486 debugging("You should really redirect before you start page output");
487 if (!$debugdisableredirect) {
488 $this->page->requires->js_function_call('document.location.replace', array($url), false, $delay);
489 }
490 $output = $this->opencontainers->pop_all_but_last();
491 break;
492 case moodle_page::STATE_DONE :
493 // Too late to be calling redirect now
494 throw new coding_exception('You cannot redirect after the entire page has been generated');
495 break;
496 }
3c0c2bf0 497
2fd7abbb 498 $output .= $this->notification($message, 'redirectmessage');
2fd7abbb 499 $output .= '<div class="continuebutton"><a data-ajax="false" data-role="button" href="'. $encodedurl .'">'. get_string('continue') .'</a></div>';
2fd7abbb 500 if ($debugdisableredirect) {
501 $output .= '<p><strong>Error output, so disabling automatic redirect.</strong></p>';
502 }
503 $output .= $this->footer();
504 return $output;
505 }
2fd7abbb 506
3c0c2bf0
SH
507 /**
508 * Renders a help icon
509 *
510 * @param help_icon $helpicon
511 * @return string
512 */
513 protected function render_help_icon(help_icon $helpicon) {
2fd7abbb 514 global $CFG;
515
516 // first get the help image icon
517 $src = $this->pix_url('help');
518
519 $title = get_string($helpicon->identifier, $helpicon->component);
520
521 if (empty($helpicon->linktext)) {
522 $alt = $title;
523 } else {
524 $alt = get_string('helpwiththis');
525 }
526
527 $attributes = array('src'=>$src, 'alt'=>$alt, 'class'=>'iconhelp', 'data-role'=>'button', 'data-inline'=>'true');
528 $output = html_writer::empty_tag('img', $attributes);
529
530 // add the link text if given
531 if (!empty($helpicon->linktext)) {
532 // the spacing has to be done through CSS
533 $output .= $helpicon->linktext;
534 }
535
536 // now create the link around it
3c0c2bf0 537 // TODO: Do we need to specify the theme in the help.php link?
2fd7abbb 538 $url = new moodle_url('/help.php', array('component' => $helpicon->component, 'identifier' => $helpicon->identifier, 'lang'=>current_language(), 'theme'=>'mymobile'));
539
540 // note: this title is displayed only if JS is disabled, otherwise the link will have the new ajax tooltip
541 $title = get_string('helpprefix2', '', trim($title, ". \t"));
542
543 $attributes = array('href'=>$url, 'title'=>$title);
544 $id = html_writer::random_id('helpicon');
545 $attributes['id'] = $id;
546 $attributes['rel'] = 'notexternal';
547 $attributes['data-rel'] = 'dialog';
548 $attributes['data-transition'] = 'slideup';
549 $output = html_writer::tag('a', $output, $attributes);
550
551 // and finally span
552 return html_writer::tag('span', $output, array('class' => 'helplink2'));
553 }
2fd7abbb 554
3c0c2bf0
SH
555 /**
556 * Renders a single button
557 *
558 * @param single_button $button
559 * @return string
560 */
561 protected function render_single_button(single_button $button) {
562 $attributes = array(
563 'type' => 'submit',
564 'value' => $button->label,
565 'disabled' => $button->disabled ? 'disabled' : null,
566 'title' => $button->tooltip
567 );
2fd7abbb 568
569 if ($button->actions) {
570 $id = html_writer::random_id('single_button');
571 $attributes['id'] = $id;
572 foreach ($button->actions as $action) {
573 $this->add_action_handler($action, $id);
574 }
575 }
576
577 // first the input element
578 $output = html_writer::empty_tag('input', $attributes);
579
580 // then hidden fields
581 $params = $button->url->params();
582 if ($button->method === 'post') {
583 $params['sesskey'] = sesskey();
584 }
585 foreach ($params as $var => $val) {
586 $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => $var, 'value' => $val));
587 }
588
589 // then div wrapper for xhtml strictness
3c0c2bf0
SH
590 $output = html_writer::tag('div', $output, array('rel' => $button->url->out_omit_querystring()));
591
592 // TODO: Test a single_button that has an anchor and is set to use post
2fd7abbb 593 // now the form itself around it
594 $url = $button->url->out_omit_querystring(); // url without params
3c0c2bf0
SH
595
596 if ($url === '') {
2fd7abbb 597 $url = '#'; // there has to be always some action
598 }
3c0c2bf0
SH
599
600 // TODO: This is surely a bug that needs fixing.. all of a sudden we've switched
601 // to the pages URL.
602 // Test an single button with an external URL as its url
603 // If the url has http, cool, if not we need to add it, JOHN
604 $urlcheck = substr($url, 0, 4);
605 if ($urlcheck != 'http') {
606 $url = $this->page->url->out_omit_querystring();
607 }
608
609 $attributes = array(
610 'method' => $button->method,
611 'action' => $url,
612 'id' => $button->formid
613 );
2fd7abbb 614 $output = html_writer::tag('form', $output, $attributes);
615
616 // and finally one more wrapper with class
617 return html_writer::tag('div', $output, array('class' => $button->class));
618 }
3c0c2bf0
SH
619
620 /**
621 * Renders the header for the page
622 *
623 * @return string
624 */
625 public function header() {
2fd7abbb 626 global $USER, $CFG;
627
628 if (session_is_loggedinas()) {
629 $this->page->add_body_class('userloggedinas');
630 }
3c0c2bf0 631
2fd7abbb 632 $this->page->set_state(moodle_page::STATE_PRINTING_HEADER);
633
634 // Find the appropriate page layout file, based on $this->page->pagelayout.
2fd7abbb 635 $layoutfile = $this->page->theme->layout_file($this->page->pagelayout);
636 // Render the layout using the layout file.
637 $rendered = $this->render_page_layout($layoutfile);
638
639 // Slice the rendered output into header and footer.
3c0c2bf0 640 $cutpos = strpos($rendered, $this->unique_main_content_token);
2fd7abbb 641 if ($cutpos === false) {
3c0c2bf0
SH
642 $cutpos = strpos($rendered, self::MAIN_CONTENT_TOKEN);
643 $token = self::MAIN_CONTENT_TOKEN;
644 } else {
645 $token = $this->unique_main_content_token;
646 }
647
648 if ($cutpos === false) {
649 // TODO: Search for a better solution to this... check this is even needed?
650 // The following code will lead to header containing nothing, and
651 // footer containing all of the content for the template.
652 // turned off error by john for ajax load of blocks without main content.
653 // throw new coding_exception('page layout file ' . $layoutfile .
2fd7abbb 654 // ' does not contain the string "' . self::MAIN_CONTENT_TOKEN . '".');
655 }
656 $header = substr($rendered, 0, $cutpos);
3c0c2bf0 657 $footer = substr($rendered, $cutpos + strlen($token));
2fd7abbb 658
659 if (empty($this->contenttype)) {
660 debugging('The page layout file did not call $OUTPUT->doctype()');
661 $header = $this->doctype() . $header;
662 }
663
664 send_headers($this->contenttype, $this->page->cacheable);
665
666 $this->opencontainers->push('header/footer', $footer);
667 $this->page->set_state(moodle_page::STATE_IN_BODY);
668
669 return $header . $this->skip_link_target('maincontent');
670 }
671
3c0c2bf0
SH
672 /**
673 * Renders a notification
674 *
675 * @param string $message
676 * @param string $classes
677 * @return string
678 */
679 public function notification($message, $classes = 'notifyproblem') {
2fd7abbb 680 return html_writer::tag('div', clean_text($message), array('data-role'=>'none', 'data-icon'=>'alert', 'data-theme'=>'d', 'class' => renderer_base::prepare_classes($classes)));
681 }
3c0c2bf0
SH
682
683 /**
684 * Renders the blocks for a block region in the page
685 *
686 * @param type $region
687 * @return string
688 */
689 public function blocks_for_region($region) {
2fd7abbb 690 $blockcontents = $this->page->blocks->get_content_for_region($region, $this);
cf2de1cf 691
2fd7abbb 692 $output = '';
693 foreach ($blockcontents as $bc) {
694 if ($bc instanceof block_contents) {
3c0c2bf0
SH
695 // We don't want to print navigation and settings blocks here.
696 if ($bc->attributes['class'] != 'block_settings block' && $bc->attributes['class'] != 'block_navigation block') {
2fd7abbb 697 $output .= $this->block($bc, $region);
698 }
699 } else if ($bc instanceof block_move_target) {
700 $output .= $this->block_move_target($bc);
701 } else {
702 throw new coding_exception('Unexpected type of thing (' . get_class($bc) . ') found in list of block contents.');
703 }
704 }
3c0c2bf0 705
2fd7abbb 706 return $output;
707 }
708
3c0c2bf0
SH
709 /**
710 * Renders a single select instance
711 *
712 * @param single_select $select
713 * @return string
714 */
715 protected function render_single_select(single_select $select) {
2fd7abbb 716 $select = clone($select);
717 if (empty($select->formid)) {
718 $select->formid = html_writer::random_id('single_select_f');
719 }
720
721 $output = '';
722 $params = $select->url->params();
723 if ($select->method === 'post') {
724 $params['sesskey'] = sesskey();
725 }
726 foreach ($params as $name=>$value) {
727 $output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>$name, 'value'=>$value));
728 }
729
730 if (empty($select->attributes['id'])) {
731 $select->attributes['id'] = html_writer::random_id('single_select');
3c0c2bf0
SH
732 //$select->attributes['data-native-menu'] = 'false';
733 //above by john for select elements to use native style and help performance?
2fd7abbb 734 }
735
736 if ($select->disabled) {
737 $select->attributes['disabled'] = 'disabled';
738 }
739
740 if ($select->tooltip) {
741 $select->attributes['title'] = $select->tooltip;
742 }
743
744 if ($select->label) {
745 $output .= html_writer::label($select->label, $select->attributes['id']);
746 }
747
748 if ($select->helpicon instanceof help_icon) {
749 $output .= $this->render($select->helpicon);
750 } else if ($select->helpicon instanceof old_help_icon) {
751 $output .= $this->render($select->helpicon);
752 }
753
754 $output .= html_writer::select($select->options, $select->name, $select->selected, $select->nothing, $select->attributes);
3c0c2bf0 755
2fd7abbb 756 //by john show go button to fix selects
757 $go = '';
3c0c2bf0
SH
758 $output .= html_writer::empty_tag('input data-inline="true"', array('type' => 'submit', 'value' => get_string('go')));
759 $output .= html_writer::tag('noscript', html_writer::tag('div', $go), array('style' => 'inline'));
2fd7abbb 760
761 $nothing = empty($select->nothing) ? false : key($select->nothing);
762 $this->page->requires->js_init_call('M.util.init_select_autosubmit', array($select->formid, $select->attributes['id'], $nothing));
763
764 // then div wrapper for xhtml strictness
765 $output = html_writer::tag('div', $output);
766
767 // now the form itself around it
3c0c2bf0
SH
768 $formattributes = array(
769 'method' => $select->method,
770 'action' => $select->url->out_omit_querystring(),
771 'id' => $select->formid
772 );
2fd7abbb 773 $output = html_writer::tag('form', $output, $formattributes);
774
775 // and finally one more wrapper with class
776 return html_writer::tag('div', $output, array('class' => $select->class));
777 }
2fd7abbb 778}
779
3c0c2bf0
SH
780/**
781 * Overridden choie module renderer for the mymobile theme
782 *
783 * @package theme
784 * @subpackage mymobile
785 * @copyright John Stabinger
786 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
787 */
2fd7abbb 788class theme_mymobile_mod_choice_renderer extends plugin_renderer_base {
789
790 /**
791 * Returns HTML to display choices of option
792 * @param object $options
793 * @param int $coursemoduleid
794 * @param bool $vertical
795 * @return string
796 */
797 public function display_options($options, $coursemoduleid, $vertical = false) {
798 $layoutclass = 'horizontal';
799 if ($vertical) {
800 $layoutclass = 'vertical';
801 }
802 $target = new moodle_url('/mod/choice/view.php');
803 //changed below to post from target john
804 $attributes = array('method'=>'POST', 'action'=>$target, 'class'=> $layoutclass);
805
806 $html = html_writer::start_tag('form', $attributes);
807 $html .= html_writer::start_tag('ul', array('class'=>'choices', 'data-role'=>'controlgroup' ));
3c0c2bf0 808
2fd7abbb 809 $availableoption = count($options['options']);
810 foreach ($options['options'] as $option) {
3c0c2bf0 811 $html .= html_writer::start_tag('li', array('class'=>'option'));
2fd7abbb 812 $option->attributes->name = 'answer';
813 $option->attributes->type = 'radio';
3c0c2bf0 814 $option->attributes->id = 'answer'.html_writer::random_id();
2fd7abbb 815
816 $labeltext = $option->text;
817 if (!empty($option->attributes->disabled)) {
818 $labeltext .= ' ' . get_string('full', 'choice');
819 $availableoption--;
820 }
821
822 $html .= html_writer::empty_tag('input', (array)$option->attributes);
823 $html .= html_writer::tag('label', $labeltext, array('for'=>$option->attributes->id));
824 $html .= html_writer::end_tag('li');
825 }
826 $html .= html_writer::tag('li','', array('class'=>'clearfloat'));
827 $html .= html_writer::end_tag('ul');
828 $html .= html_writer::tag('div', '', array('class'=>'clearfloat'));
829 $html .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'sesskey', 'value'=>sesskey()));
830 $html .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'id', 'value'=>$coursemoduleid));
831
832 if (!empty($options['hascapability']) && ($options['hascapability'])) {
833 if ($availableoption < 1) {
834 $html .= html_writer::tag('label', get_string('choicefull', 'choice'));
835 } else {
836 $html .= html_writer::empty_tag('input', array('type'=>'submit', 'value'=>get_string('savemychoice','choice'), 'class'=>'button'));
837 }
838
839 if (!empty($options['allowupdate']) && ($options['allowupdate'])) {
840 $url = new moodle_url('view.php', array('id'=>$coursemoduleid, 'action'=>'delchoice', 'sesskey'=>sesskey()));
841 $html .= html_writer::link($url, get_string('removemychoice','choice'));
842 }
843 } else {
844 $html .= html_writer::tag('label', get_string('havetologin', 'choice'));
845 }
846
847 $html .= html_writer::end_tag('ul');
848 $html .= html_writer::end_tag('form');
849
850 return $html;
851 }
852
853 /**
854 * Returns HTML to display choices result
3c0c2bf0
SH
855 *
856 * TODO: There are differences between this method and the mod choice renderers function.
857 * This needs to be checked VERY careful as the minor changes look like they
858 * may lead to regressions.
859 *
2fd7abbb 860 * @param object $choices
861 * @param bool $forcepublish
862 * @return string
863 */
864 public function display_publish_name_vertical($choices) {
865 $html ='';
866 $html .= html_writer::tag('h2',format_string(get_string("responses", "choice")), array('class'=>'main'));
867
868 $attributes = array('method'=>'POST');
869 $attributes['action'] = new moodle_url('/mod/choice/view.php');
870 $attributes['id'] = 'attemptsform';
871
872 if ($choices->viewresponsecapability) {
873 $html .= html_writer::start_tag('form', $attributes);
874 $html .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'id', 'value'=> $choices->coursemoduleid));
875 $html .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'sesskey', 'value'=> sesskey()));
876 $html .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'mode', 'value'=>'overview'));
877 }
878
879 $table = new html_table();
880 $table->cellpadding = 0;
881 $table->cellspacing = 0;
882 $table->attributes['class'] = 'results names ';
883 $table->tablealign = 'center';
884 $table->data = array();
885
886 $count = 0;
887 ksort($choices->options);
888
889 $columns = array();
890 foreach ($choices->options as $optionid => $options) {
891 $coldata = '';
892 if ($choices->showunanswered && $optionid == 0) {
893 $coldata .= html_writer::tag('div', format_string(get_string('notanswered', 'choice')), array('class'=>'option'));
894 } else if ($optionid > 0) {
895 $coldata .= html_writer::tag('div', format_string($choices->options[$optionid]->text), array('class'=>'option'));
896 }
897 $numberofuser = 0;
898 if (!empty($options->user) && count($options->user) > 0) {
899 $numberofuser = count($options->user);
900 }
901
902 $coldata .= html_writer::tag('div', ' ('.$numberofuser. ')', array('class'=>'numberofuser', 'title' => get_string('numberofuser', 'choice')));
903 $columns[] = $coldata;
904 }
905
906 $table->head = $columns;
907
908 $coldata = '';
909 $columns = array();
910 foreach ($choices->options as $optionid => $options) {
911 $coldata = '';
912 if ($choices->showunanswered || $optionid > 0) {
913 if (!empty($options->user)) {
914 foreach ($options->user as $user) {
915 $data = '';
916 if (empty($user->imagealt)){
917 $user->imagealt = '';
918 }
919
920 if ($choices->viewresponsecapability && $choices->deleterepsonsecapability && $optionid > 0) {
921 $attemptaction = html_writer::checkbox('attemptid[]', $user->id,'');
922 $data .= html_writer::tag('div', $attemptaction, array('class'=>'attemptaction'));
923 }
924 $userimage = $this->output->user_picture($user, array('courseid'=>$choices->courseid));
925 $data .= html_writer::tag('div', $userimage, array('class'=>'image'));
926
927 $userlink = new moodle_url('/user/view.php', array('id'=>$user->id,'course'=>$choices->courseid));
928 $name = html_writer::tag('a', fullname($user, $choices->fullnamecapability), array('href'=>$userlink, 'class'=>'username'));
929 $data .= html_writer::tag('div', $name, array('class'=>'fullname'));
930 $data .= html_writer::tag('div','', array('class'=>'clearfloat'));
931 $coldata .= html_writer::tag('div', $data, array('class'=>'user'));
932 }
933 }
934 }
935
936 $columns[] = $coldata;
937 $count++;
938 }
939
940 $table->data[] = $columns;
941 foreach ($columns as $d) {
942 $table->colclasses[] = 'data';
943 }
944 $html .= html_writer::tag('div', html_writer::table($table), array('class'=>'response'));
945
946 $actiondata = '';
947 if ($choices->viewresponsecapability && $choices->deleterepsonsecapability) {
948 $selecturl = new moodle_url('#');
949
950 $selectallactions = new component_action('click',"select_all_in", array('div',null,'tablecontainer'));
951 $selectall = new action_link($selecturl, get_string('selectall'), $selectallactions);
952 $actiondata .= $this->output->render($selectall) . ' / ';
953
954 $deselectallactions = new component_action('click',"deselect_all_in", array('div',null,'tablecontainer'));
955 $deselectall = new action_link($selecturl, get_string('deselectall'), $deselectallactions);
956 $actiondata .= $this->output->render($deselectall);
957 //below john fixed
958 $actiondata .= html_writer::tag('label', ' ' . get_string('withselected', 'choice') . ' ', array('for'=>'menuaction'));
959
960 $actionurl = new moodle_url('/mod/choice/view.php', array('sesskey'=>sesskey(), 'action'=>'delete_confirmation()'));
961 $select = new single_select($actionurl, 'action', array('delete'=>get_string('delete')), null, array(''=>get_string('moveselectedusersto', 'choice')), 'attemptsform');
962
963 $actiondata .= $this->output->render($select);
964 }
965 $html .= html_writer::tag('div', $actiondata, array('class'=>'responseaction'));
966
967 if ($choices->viewresponsecapability) {
968 $html .= html_writer::end_tag('form');
969 }
970
971 return $html;
972 }
cf2de1cf 973}