PageRenderTime 27ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/renderer.php

https://github.com/KieranRBriggs/moodle-mod_hotpot
PHP | 926 lines | 630 code | 100 blank | 196 comment | 150 complexity | 6e36b74400ffc0786b6be4e2acff3a99 MD5 | raw file
  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. /**
  17. * All hotpot module renderers are defined here
  18. *
  19. * @package mod-hotpot
  20. * @copyright 2010 Gordon Bateson <gordon.bateson@gmail.com>
  21. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22. */
  23. defined('MOODLE_INTERNAL') || die();
  24. /**
  25. * Hotpot module renderer class
  26. *
  27. * @copyright 2010 Gordon Bateson <gordon.bateson@gmail.com>
  28. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  29. */
  30. class mod_hotpot_renderer extends plugin_renderer_base {
  31. /////////////////////////////////////////////////////////////////////
  32. // functions to generate common html snippets //
  33. /////////////////////////////////////////////////////////////////////
  34. /**
  35. * form_start
  36. *
  37. * @param xxx $hotpotscriptname
  38. * @param xxx $params
  39. * @param xxx $attributes (optional, default=array)
  40. * @return xxx
  41. */
  42. function form_start($hotpotscriptname, $params, $attributes=array()) {
  43. $output = '';
  44. if (empty($attributes['method'])) {
  45. $attributes['method'] = 'post';
  46. }
  47. if (empty($attributes['action'])) {
  48. $url = new moodle_url('/mod/hotpot/'.$hotpotscriptname);
  49. $attributes['action'] = $url->out();
  50. }
  51. $output .= html_writer::start_tag('form', $attributes)."\n";
  52. $hiddenfields = '';
  53. foreach ($params as $name => $value) {
  54. $hiddenfields .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>$name, 'value'=>$value))."\n";
  55. }
  56. if ($hiddenfields) {
  57. // xhtml strict requires a container for the hidden input elements
  58. $output .= html_writer::start_tag('fieldset', array('style'=>'display:none'))."\n";
  59. $output .= $hiddenfields;
  60. $output .= html_writer::end_tag('fieldset')."\n";
  61. }
  62. // xhtml strict requires a container for the contents of the <form>
  63. $output .= html_writer::start_tag('div')."\n";
  64. return $output;
  65. }
  66. /**
  67. * form_end
  68. *
  69. * @return xxx
  70. */
  71. function form_end() {
  72. $output = '';
  73. $output .= html_writer::end_tag('div')."\n";
  74. $output .= html_writer::end_tag('form')."\n";
  75. return $output;
  76. }
  77. ////////////////////////////////////////////////////////////////////////////
  78. // Helper methods //
  79. ////////////////////////////////////////////////////////////////////////////
  80. /**
  81. * format_url
  82. *
  83. * @param xxx $url
  84. * @param xxx $id
  85. * @param xxx $params
  86. * @param xxx $more_params (optional, default=false)
  87. * @return xxx
  88. */
  89. function format_url($url, $id, $params, $more_params=false) {
  90. global $CFG;
  91. // convert relative URL to absolute URL
  92. if (! preg_match('/^(https?:\/)?\//', $url)) {
  93. $url = $CFG->wwwroot.'/mod/hotpot/'.$url;
  94. }
  95. // merge parameters into a single array
  96. $all_params = array_merge($params, $more_params);
  97. // rename the $id parameter, if necesary
  98. if ($id && isset($all_params[$id])) {
  99. $all_params['id'] = $all_params[$id];
  100. unset($all_params[$id]);
  101. }
  102. $join = '?';
  103. foreach ($all_params as $name=>$value) {
  104. if ($value) {
  105. $url .= $join.$name.'='.$value;
  106. $join = '&amp;';
  107. }
  108. }
  109. return $url;
  110. }
  111. /**
  112. * print_commands
  113. *
  114. * @param xxx $types
  115. * @param xxx $hotpotscriptname
  116. * @param xxx $id
  117. * @param xxx $params
  118. * @param xxx $popup (optional, default=false)
  119. * @param xxx $return (optional, default=false)
  120. * @return xxx
  121. */
  122. function print_commands($types, $hotpotscriptname, $id, $params, $popup=false, $return=false) {
  123. // $types : array('add', 'update', 'delete', 'deleteall')
  124. // $params : array('name' => 'value') for url query string
  125. // $popup : true, false or array('name' => 'something', 'width' => 999, 'height' => 999)
  126. $commands = html_writer::start_tag('span', array('class'=>'commands'))."\n";
  127. foreach ($types as $type) {
  128. $commands .= $this->print_command($type, $hotpotscriptname, $id, $params, $popup, $return);
  129. }
  130. $commands .= html_writer::end_tag('form')."\n";
  131. if ($return) {
  132. return $commands;
  133. } else {
  134. print $commands;
  135. }
  136. }
  137. /**
  138. * print_command
  139. *
  140. * @param xxx $type
  141. * @param xxx $hotpotscriptname
  142. * @param xxx $id
  143. * @param xxx $params
  144. * @param xxx $popup (optional, default=false)
  145. * @param xxx $return (optional, default=false)
  146. * @return xxx
  147. */
  148. function print_command($type, $hotpotscriptname, $id, $params, $popup=false, $return=false) {
  149. global $CFG;
  150. static $str;
  151. if (! isset($str)) {
  152. $str = new stdClass();
  153. }
  154. if (! isset($str->$type)) {
  155. $str->$type = get_string($type);
  156. }
  157. switch ($type) {
  158. case 'add':
  159. $icon = '';
  160. break;
  161. case 'edit':
  162. case 'update':
  163. $icon = 't/edit';
  164. break;
  165. case 'delete':
  166. $icon = 't/delete.gif';
  167. break;
  168. case 'deleteall':
  169. $icon = '';
  170. break;
  171. default:
  172. // unknown command type !!
  173. return '';
  174. }
  175. foreach ($params as $key => $value) {
  176. if (empty($value)) {
  177. unset($params[$key]);
  178. }
  179. }
  180. $params['action'] = $type;
  181. $url = new moodle_url('/mod/hotpot/'.$hotpotscriptname, $params);
  182. if ($icon) {
  183. $linktext = $this->action_icon($url, new pix_icon($icon, get_string($type)));
  184. } else {
  185. $linktext = $str->$type;
  186. }
  187. if ($popup) {
  188. if (is_bool($popup)) {
  189. $popup = array();
  190. } else if (is_string($popup)) {
  191. $popup = array('name' => $popup);
  192. }
  193. $name = (isset($popup['name']) ? $popup['name'] : '');
  194. $width = (isset($popup['width']) ? $popup['width'] : 650);
  195. $height = (isset($popup['height']) ? $popup['height'] : 400);
  196. $command = element_to_popup_window(
  197. // $type, $url, $name, $linktext, $height, $width, $title, $options, $return, $id, $class
  198. 'link', $url, $name, $linktext, $height, $width, $str->$type, '', true, '', ''
  199. );
  200. } else {
  201. $command = html_writer::link($url, $linktext, array('title' => $str->$type))."\n";
  202. }
  203. if (! $icon) {
  204. // add white space between text commands
  205. $command .= ' &nbsp; ';
  206. }
  207. if ($return) {
  208. return ' '.$command;
  209. } else {
  210. print ' '.$command;
  211. }
  212. }
  213. /**
  214. * heading
  215. *
  216. * @global object $hotpot
  217. * @return string
  218. */
  219. public function heading($hotpot) {
  220. $text = format_string($hotpot->name);
  221. if ($hotpot->can_manage()) {
  222. $text .= $this->modedit_icon($hotpot);
  223. }
  224. return parent::heading($text);
  225. }
  226. /**
  227. * modedit_icon
  228. *
  229. * @global object $hotpot
  230. * @return string
  231. */
  232. public function modedit_icon($hotpot) {
  233. $params = array('update' => $hotpot->cm->id, 'return' => 1, 'sesskey' => sesskey());
  234. $url = new moodle_url('/course/modedit.php', $params);
  235. $img = html_writer::empty_tag('img', array('src' => $this->pix_url('t/edit')));
  236. return ' '.html_writer::link($url, $img);
  237. }
  238. /**
  239. * Formats hotpot entry/exit description text
  240. *
  241. * @global object $CFG
  242. * @param object $hotpot instance of activity
  243. * @param string $type of page, either "entry" or "exit"
  244. * @return string
  245. */
  246. public function description_box($hotpot, $type='') {
  247. global $CFG;
  248. require_once($CFG->dirroot.'/lib/filelib.php');
  249. if ($type) {
  250. $textfield = $type.'text';
  251. $formatfield = $type.'format';
  252. } else {
  253. $type = 'intro';
  254. $textfield = 'intro';
  255. $formatfield = 'introformat';
  256. }
  257. $text = '';
  258. if (trim(strip_tags($hotpot->$textfield))) {
  259. $options = (object)array('noclean'=>true, 'para'=>false, 'filter'=>true, 'context'=>$hotpot->context);
  260. $text = file_rewrite_pluginfile_urls($hotpot->$textfield, 'pluginfile.php', $hotpot->context->id, 'mod_hotpot', $type, null);
  261. $text = trim(format_text($text, $hotpot->$formatfield, $options, null));
  262. }
  263. if ($text) {
  264. return $this->box($text, 'generalbox', 'intro');
  265. } else {
  266. return '';
  267. }
  268. }
  269. /**
  270. * entryoptions
  271. *
  272. * @param xxx $hotpot
  273. * @return xxx
  274. */
  275. public function entryoptions($hotpot) {
  276. $output = '';
  277. $table = new html_table();
  278. // define the date format - can be one of the following:
  279. // strftimerecentfull, strftimedaydatetime, strftimedatetime
  280. $dateformat = get_string('strftimedaydatetime');
  281. // show open / close dates
  282. if ($hotpot->entryoptions & hotpot::ENTRYOPTIONS_DATES) {
  283. if ($hotpot->timeopen) {
  284. $table->data[] = new html_table_row(array(
  285. new html_table_cell(get_string('timeopen', 'hotpot').':'),
  286. new html_table_cell(userdate($hotpot->timeopen, $dateformat))
  287. ));
  288. }
  289. if ($hotpot->timeclose) {
  290. $table->data[] = new html_table_row(array(
  291. new html_table_cell(get_string('timeclose', 'hotpot').':'),
  292. new html_table_cell(userdate($hotpot->timeclose, $dateformat))
  293. ));
  294. }
  295. }
  296. // show grading info
  297. if ($hotpot->entryoptions & hotpot::ENTRYOPTIONS_GRADING) {
  298. if ($hotpot->attemptlimit > 1) {
  299. $table->data[] = new html_table_row(array(
  300. new html_table_cell(get_string('attemptsallowed', 'quiz').':'),
  301. new html_table_cell($hotpot->attemptlimit)
  302. ));
  303. }
  304. if ($hotpot->timelimit > 0) {
  305. $table->data[] = new html_table_row(array(
  306. new html_table_cell(get_string('timelimit', 'hotpot').':'),
  307. new html_table_cell(format_time($hotpot->timelimit))
  308. ));
  309. }
  310. if ($hotpot->gradeweighting && $hotpot->attemptlimit != 1) {
  311. $table->data[] = new html_table_row(array(
  312. new html_table_cell(get_string('grademethod', 'hotpot').':'),
  313. new html_table_cell($hotpot->format_grademethod())
  314. ));
  315. }
  316. }
  317. if (count($table->data)) {
  318. $table->attributes['class'] = 'hotpotentryoptions';
  319. $output .= html_writer::table($table);
  320. }
  321. // print summary of attempts by this user at this unit
  322. if ($hotpot->entryoptions & hotpot::ENTRYOPTIONS_ATTEMPTS) {
  323. $output .= $this->attemptssummary($hotpot);
  324. }
  325. return $output;
  326. }
  327. /**
  328. * entrywarnings
  329. *
  330. * @param xxx $hotpot
  331. * @return xxx
  332. */
  333. public function entrywarnings($hotpot) {
  334. $warnings = array();
  335. $canstart = true;
  336. if (! $hotpot->can_preview()) {
  337. if ($error = $hotpot->require_subnet()) {
  338. // IP-address is not in allowable range
  339. $warnings[] = $error;
  340. $canstart = false;
  341. }
  342. if ($error = $hotpot->require_isopen()) {
  343. // hotpot is not (yet) open
  344. $warnings[] = $error;
  345. $canstart = false;
  346. }
  347. if ($error = $hotpot->require_notclosed()) {
  348. // hotpot is (already) closed
  349. $warnings[] = $error;
  350. $canstart = false;
  351. }
  352. if ($error = $hotpot->require_entrycm()) {
  353. // minimum grade for previous activity not satisfied
  354. $warnings[] = $error;
  355. $canstart = false;
  356. }
  357. if ($error = $hotpot->require_delay('delay1')) {
  358. // delay1 has not expired yet
  359. $warnings[] = $error;
  360. $canstart = false;
  361. }
  362. if ($error = $hotpot->require_delay('delay2')) {
  363. // delay2 has not expired yet
  364. $warnings[] = $error;
  365. $canstart = false;
  366. }
  367. if ($error = $hotpot->require_moreattempts(true)) {
  368. // maximum number of attempts reached
  369. $warnings[] = $error;
  370. $canstart = false;
  371. }
  372. if ($canstart) {
  373. if ($error = $hotpot->require_password()) {
  374. // password not given yet
  375. $warnings[] = $error;
  376. $canstart = false;
  377. }
  378. }
  379. }
  380. // cache the boolean flags in case they are needed later - see $this->view_attempt_button()
  381. $hotpot->can_start($canstart);
  382. if (count($warnings)) {
  383. return $this->box(html_writer::alist($warnings), 'generalbox', 'hotpotwarnings');
  384. } else {
  385. return '';
  386. }
  387. }
  388. /**
  389. * attemptssummary
  390. *
  391. * @param xxx $hotpot
  392. * @return xxx
  393. */
  394. public function attemptssummary($hotpot) {
  395. global $CFG;
  396. if (! $countattempts = $hotpot->get_attempts()) {
  397. return '';
  398. }
  399. $output = '';
  400. // array to store attemptids of certain kinds of attempts
  401. $attemptids = array(
  402. 'all' => array(),
  403. 'inprogress' => array(),
  404. 'timedout' => array(),
  405. 'abandoned' => array(),
  406. 'completed' => array(),
  407. 'zeroduration' => array(),
  408. 'zeroscore' => array()
  409. );
  410. $dateformat = get_string('strftimerecentfull');
  411. // cache selectcolumn switch
  412. if ($hotpot->can_deleteattempts()) {
  413. $showselectcolumn = true;
  414. } else {
  415. $showselectcolumn = false;
  416. }
  417. // cache report links flag
  418. if ($hotpot->can_reviewattempts()) {
  419. $showreportlinks = true;
  420. } else {
  421. $showreportlinks = false;
  422. }
  423. // set resume tab text
  424. if ($hotpot->can_preview()) {
  425. $resumetab = 'preview';
  426. } else if ($hotpot->can_view()) {
  427. $resumetab = 'info';
  428. } else {
  429. $resumetab = '';
  430. }
  431. // start attempts table (info + resume buttons)
  432. $table = new html_table();
  433. $table->attributes['class'] = 'hotpotattemptssummary';
  434. $table->head = array(
  435. get_string('attemptnumber', 'hotpot'),
  436. get_string('status', 'hotpot'),
  437. get_string('duration', 'hotpot'),
  438. get_string('lastaccess', 'hotpot')
  439. );
  440. $table->align = array('center', 'center', 'left', 'left');
  441. $table->size = array('', '', '', '');
  442. if ($hotpot->gradeweighting) {
  443. // insert grade column
  444. array_splice($table->head, 1, 0, array(get_string('score', 'hotpot')));
  445. array_splice($table->align, 1, 0, array('center'));
  446. array_splice($table->size, 1, 0, array(''));
  447. }
  448. if ($showselectcolumn) {
  449. // prepend select column
  450. array_splice($table->head, 0, 0, '&nbsp;');
  451. array_splice($table->align, 0, 0, array('center'));
  452. array_splice($table->size, 0, 0, array(''));
  453. }
  454. // echo rows of attempt info
  455. foreach ($hotpot->attempts as $attempt) {
  456. $row = new html_table_row();
  457. // set duration
  458. if ($attempt->timestart && $attempt->timefinish) {
  459. $duration = $attempt->timefinish - $attempt->timestart;
  460. } else if ($attempt->starttime && $attempt->endtime) {
  461. $duration = $attempt->endtime - $attempt->starttime;
  462. } else if ($attempt->timestart && $attempt->timemodified) {
  463. $duration = $attempt->timemodified - $attempt->timestart;
  464. } else {
  465. $duration = 0;
  466. }
  467. if ($showselectcolumn) {
  468. $id = '['.$attempt->id.']';
  469. $row->cells[] = new html_table_cell(html_writer::checkbox('selected'.$id, 1, false));
  470. switch ($attempt->status) {
  471. case hotpot::STATUS_INPROGRESS: $attemptids['inprogress'][] = $id; break;
  472. case hotpot::STATUS_TIMEDOUT: $attemptids['timedout'][] = $id; break;
  473. case hotpot::STATUS_ABANDONED: $attemptids['abandoned'][] = $id; break;
  474. case hotpot::STATUS_COMPLETED: $attemptids['completed'][] = $id; break;
  475. }
  476. if ($attempt->score==0) {
  477. $attemptids['zeroscore'][] = $id;
  478. }
  479. if ($duration==0) {
  480. $attemptids['zeroduration'][] = $id;
  481. }
  482. $attemptids['all'][] = $id;
  483. }
  484. $row->cells[] = new html_table_cell($attempt->attempt);
  485. if ($hotpot->gradeweighting) {
  486. $text = $attempt->score.'%';
  487. if ($showreportlinks) {
  488. $url = $hotpot->review_url($attempt);
  489. $text = html_writer::link($url, $text);
  490. }
  491. $row->cells[] = new html_table_cell($text);
  492. }
  493. $row->cells[] = new html_table_cell($hotpot->format_status($attempt->status));
  494. $row->cells[] = new html_table_cell($hotpot->format_time($duration));
  495. $row->cells[] = new html_table_cell(userdate($attempt->timemodified, $dateformat));
  496. $table->data[] = $row;
  497. }
  498. // start form if necessary
  499. if ($showselectcolumn) {
  500. $onsubmit = ''
  501. ."var x=false;"
  502. ."var obj=document.getElementsByTagName('input');"
  503. ."if(obj){"
  504. ."for(var i in obj){"
  505. ."if(obj[i].name && obj[i].name.substr(0,9)=='selected[' && obj[i].checked){"
  506. ."x=true;"
  507. ."break;"
  508. ."}"
  509. ."}"
  510. ."if(!x){"
  511. ."alert('".get_string('checksomeboxes', 'hotpot')."');"
  512. ."}"
  513. ."}"
  514. ."if(x){"
  515. ."x=confirm('".get_string('confirmdeleteattempts', 'hotpot')."');"
  516. ."}"
  517. ."if(this.elements['confirmed']){"
  518. ."this.elements['confirmed'].value=(x?1:0);"
  519. ."}"
  520. ."return x;"
  521. ;
  522. $params = array(
  523. 'id' => $hotpot->cm->id, 'sesskey' => sesskey(), 'confirmed' => 0, 'action' => 'deleteselected'
  524. );
  525. $output .= $this->form_start('view.php', $params, array('onsubmit' => $onsubmit))."\n";
  526. }
  527. // echo the summary of attempts
  528. $output .= html_writer::table($table);
  529. // end form if necessary
  530. if ($showselectcolumn) {
  531. $output .= $this->box_start('generalbox', 'hotpotdeleteattempts');
  532. $output .= ''
  533. .'<script type="text/javascript">'."\n"
  534. .'//<!CDATA['."\n"
  535. ."function hotpot_set_checked(nameFilter, indexFilter, checkedValue) {\n"
  536. ." var partMatchName = new RegExp(nameFilter);\n"
  537. ." var fullMatchName = new RegExp(nameFilter+indexFilter);\n"
  538. ." var inputs = document.getElementsByTagName('input');\n"
  539. ." if (inputs) {\n"
  540. ." var i_max = inputs.length;\n"
  541. ." } else {\n"
  542. ." var i_max = 0;\n"
  543. ." }\n"
  544. ." for (var i=0; i<i_max; i++) {\n"
  545. ." if (inputs[i].type=='checkbox' && inputs[i].name.match(partMatchName)) {\n"
  546. ." if (inputs[i].name.match(fullMatchName)) {\n"
  547. ." inputs[i].checked = checkedValue;\n"
  548. ." } else {\n"
  549. ." inputs[i].checked = false;\n"
  550. ." }\n"
  551. ." }\n"
  552. ." }\n"
  553. ." return true;\n"
  554. ."}\n"
  555. ."function hotpot_set_checked_attempts(obj) {\n"
  556. ." var indexFilter = obj.options[obj.selectedIndex].value;\n"
  557. ." if (indexFilter=='none') {\n"
  558. ." checkedValue = 0;\n"
  559. ." } else {\n"
  560. ." checkedValue = 1;\n"
  561. ." }\n"
  562. ." if (indexFilter=='none' || indexFilter=='all') {\n"
  563. ." indexFilter = '\\\\[\\\\d+\\\\]';\n"
  564. ." } else {\n"
  565. ." indexFilter = indexFilter.replace(new RegExp('^[^:]*:'), '');\n"
  566. ." indexFilter = indexFilter.replace(new RegExp(',', 'g'), '|');\n"
  567. ." indexFilter = indexFilter.replace(new RegExp('\\\\[', 'g'), '\\\\[');\n"
  568. ." indexFilter = indexFilter.replace(new RegExp('\\\\]', 'g'), '\\\\]');\n"
  569. ." }\n"
  570. ." hotpot_set_checked('selected', indexFilter, checkedValue);"
  571. ."}\n"
  572. .'//]]>'."\n"
  573. .'</script>'."\n"
  574. ;
  575. $onchange = 'return hotpot_set_checked_attempts(this)';
  576. // set up attempt status drop down menu
  577. $options = array(
  578. 'none' => get_string('none')
  579. );
  580. foreach($attemptids as $type=>$ids) {
  581. if ($total = count($ids)) {
  582. if ($type=='all') {
  583. $options['all'] = get_string('all');
  584. if ($total > 1) {
  585. $options['all'] .= " ($total)";
  586. }
  587. } else {
  588. $options[$type.':'.implode(',', $ids)] = get_string($type, 'hotpot')." ($total)";
  589. }
  590. }
  591. }
  592. // add attempt selection/deletion form controls
  593. $table = new html_table();
  594. $table->attributes['class'] = 'hotpotdeleteattempts';
  595. $table->data[] = new html_table_row(array(
  596. new html_table_cell(get_string('selectattempts', 'hotpot').':'),
  597. new html_table_cell(html_writer::select($options, 'selectattempts', null, array(''=>'choosedots'), array('onchange'=>$onchange)))
  598. ));
  599. // original onselect was 'return hotpot_set_checked_attempts(this)'
  600. // Moodle 2.0 uses component_actions, some thing like this ...
  601. // actually this doesn't work, but it is close - maybe :-)
  602. // $action = new component_action('select', 'hotpot_set_checked_attempts', array('this'));
  603. // $this->add_action_handler($action, 'menuselectattempts');
  604. $table->data[] = new html_table_row(array(
  605. new html_table_cell('&nbsp;'),
  606. new html_table_cell(html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('deleteattempts', 'hotpot'))))
  607. ));
  608. $output .= html_writer::table($table);
  609. $output .= $this->box_end();
  610. $output .= $this->form_end();
  611. }
  612. return $output;
  613. }
  614. /**
  615. * view_attempt_button
  616. *
  617. * @param xxx $hotpot
  618. * @return xxx
  619. */
  620. function view_attempt_button($hotpot) {
  621. $output = '';
  622. // Initialize button text. This will be set something
  623. // if as start/continue attempt button should appear.
  624. $buttontext = '';
  625. if ($hotpot->can_preview()) {
  626. $buttontext = get_string('previewquiznow', 'quiz');
  627. } else if ($hotpot->can_start()) {
  628. if ($hotpot->count_distinct_clickreportids()) {
  629. $buttontext = get_string('reattemptquiz', 'quiz');
  630. } else {
  631. $buttontext = get_string('attemptquiznow', 'quiz');
  632. }
  633. }
  634. $output .= $this->box_start('hotpotviewbutton');
  635. if ($buttontext) {
  636. $url = $hotpot->attempt_url();
  637. $button = new single_button($url, $buttontext);
  638. $button->class .= ' hotpotviewbutton';
  639. $output .= $this->render($button);
  640. } else {
  641. $url = new moodle_url('/course/view.php', array('id' => $hotpot->course->id));
  642. $output .= $this->continue_button($url);
  643. }
  644. $output .= $this->box_end();
  645. return $output;
  646. }
  647. /**
  648. * whatnext
  649. *
  650. * @param xxx $str
  651. * @return xxx
  652. */
  653. public function whatnext($str='') {
  654. switch ($str) {
  655. case '':
  656. $whatnext = get_string('exit_whatnext_default', 'hotpot');
  657. break;
  658. case 'exit_whatnext':
  659. switch (mt_rand(0,1)) { // random 0 or 1. You can add more if you like
  660. case 0: $whatnext = get_string('exit_whatnext_0', 'hotpot'); break;
  661. case 1: $whatnext = get_string('exit_whatnext_1', 'hotpot'); break;
  662. }
  663. break;
  664. default:
  665. $whatnext = get_string($str, 'hotpot');
  666. }
  667. return html_writer::tag('h3', $whatnext, array('class'=>'hotpotwhatnext'));
  668. }
  669. /**
  670. * exitoptions
  671. *
  672. * @param xxx $hotpot
  673. * @return xxx
  674. */
  675. public function exitfeedback($hotpot) {
  676. global $CFG;
  677. $percentsign = '%';
  678. $feedback = array();
  679. if ($hotpot->gradeweighting==0) {
  680. if ($hotpot->exitoptions & hotpot::EXITOPTIONS_ATTEMPTSCORE || $hotpot->exitoptions & hotpot::EXITOPTIONS_HOTPOTGRADE) {
  681. $text = get_string('exit_noscore', 'hotpot');
  682. $feedback[] = html_writer::tag('li', $text);
  683. }
  684. } else if ($hotpot->get_gradeitem() && $hotpot->get_attempt()) {
  685. if ($hotpot->exitoptions & hotpot::EXITOPTIONS_ENCOURAGEMENT) {
  686. switch (true) {
  687. case $hotpot->attempt->score >= 90:
  688. $text = get_string('exit_excellent', 'hotpot');
  689. break;
  690. case $hotpot->attempt->score >= 60:
  691. $text = get_string('exit_welldone', 'hotpot');
  692. break;
  693. case $hotpot->attempt->score > 0:
  694. $text = get_string('exit_goodtry', 'hotpot');
  695. break;
  696. default:
  697. $text = get_string('exit_areyouok', 'hotpot');
  698. }
  699. $feedback[] = html_writer::tag('li', $text, array('class' => 'hotpotexitencouragement'));
  700. }
  701. if ($hotpot->exitoptions & hotpot::EXITOPTIONS_ATTEMPTSCORE) {
  702. $text = get_string('exit_attemptscore', 'hotpot', $hotpot->attempt->score.$percentsign);
  703. $feedback[] = html_writer::tag('li', $text);
  704. }
  705. if ($hotpot->exitoptions & hotpot::EXITOPTIONS_HOTPOTGRADE) {
  706. switch ($hotpot->grademethod) {
  707. case hotpot::GRADEMETHOD_HIGHEST:
  708. if ($hotpot->attempt->score < $hotpot->gradeitem->percent) {
  709. // current attempt is less than the highest so far
  710. $text = get_string('exit_hotpotgrade_highest', 'hotpot', $hotpot->gradeitem->percent.$percentsign);
  711. $feedback[] = html_writer::tag('li', $text);
  712. } else if ($hotpot->attempt->score==0) {
  713. // zero score is best so far
  714. $text = get_string('exit_hotpotgrade_highest_zero', 'hotpot', $hotpot->attempt->score.$percentsign);
  715. $feedback[] = html_writer::tag('li', $text);
  716. } else if ($hotpot->get_attempts()) {
  717. // current attempt is highest so far
  718. $maxscore = null;
  719. foreach ($hotpot->attempts as $attempt) {
  720. if ($attempt->id==$hotpot->attempt->id) {
  721. continue; // skip current attempt
  722. }
  723. if (is_null($maxscore) || $maxscore<$attempt->score) {
  724. $maxscore = $attempt->score;
  725. }
  726. }
  727. if (is_null($maxscore)) {
  728. // do nothing (no previous attempt)
  729. } else if ($maxscore==$hotpot->attempt->score) {
  730. // attempt grade equals previous best
  731. $text = get_string('exit_hotpotgrade_highest_equal', 'hotpot');
  732. $feedback[] = html_writer::tag('li', $text);
  733. } else {
  734. $text = get_string('exit_hotpotgrade_highest_previous', 'hotpot', $maxscore.$percentsign);
  735. $feedback[] = html_writer::tag('li', $text);
  736. }
  737. } else {
  738. die('oops, no attempts');
  739. }
  740. break;
  741. case hotpot::GRADEMETHOD_AVERAGE:
  742. $text = get_string('exit_hotpotgrade_average', 'hotpot', $hotpot->gradeitem->percent.$percentsign);
  743. $feedback[] = html_writer::tag('li', $text);
  744. break;
  745. // case hotpot::GRADEMETHOD_TOTAL:
  746. // case hotpot::GRADEMETHOD_FIRST:
  747. // case hotpot::GRADEMETHOD_LAST:
  748. default:
  749. $text = get_string('exit_hotpotgrade', 'hotpot', $hotpot->gradeitem->percent.$percentsign);
  750. $feedback[] = html_writer::tag('li', $text);
  751. break;
  752. }
  753. }
  754. }
  755. if (count($feedback)) {
  756. $feedback = html_writer::tag('ul', implode('', $feedback), array('class' => 'hotpotexitfeedback'));
  757. return $this->box($feedback);
  758. } else {
  759. return '';
  760. }
  761. }
  762. /**
  763. * exitlinks
  764. *
  765. * @param xxx $hotpot
  766. * @return xxx
  767. */
  768. public function exitlinks($hotpot) {
  769. $table = new html_table();
  770. $table->attributes['class'] = 'hotpotexitlinks';
  771. if ($hotpot->attempt->status==hotpot::STATUS_COMPLETED) {
  772. if ($hotpot->require_exitgrade() && $hotpot->attempt->score < $hotpot->exitgrade) {
  773. // insufficient grade to show link to next activity
  774. $cm = false;
  775. } else {
  776. // get next activity, if there is one
  777. $cm = $hotpot->get_cm('exit');
  778. }
  779. if ($cm) {
  780. $url = new moodle_url('/mod/'.$cm->modname.'/view.php', array('id' => $cm->id));
  781. $table->data[] = new html_table_row(array(
  782. new html_table_cell(html_writer::link($url, get_string('exit_next', 'hotpot'))),
  783. new html_table_cell(html_writer::link($url, format_string(urldecode($cm->name))))
  784. ));
  785. }
  786. }
  787. if ($hotpot->exitoptions & hotpot::EXITOPTIONS_RETRY) {
  788. // retry this hotpot, if allowed
  789. if ($hotpot->attemptlimit==0 || empty($hotpot->attempts) || $hotpot->attemptlimit < count($hotpot->attempts)) {
  790. $table->data[] = new html_table_row(array(
  791. new html_table_cell(html_writer::link($hotpot->view_url(), get_string('exit_retry', 'hotpot'))),
  792. new html_table_cell(html_writer::link($hotpot->view_url(), format_string($hotpot->name))),
  793. ));
  794. }
  795. }
  796. if ($hotpot->exitoptions & hotpot::EXITOPTIONS_INDEX) {
  797. $table->data[] = new html_table_row(array(
  798. new html_table_cell(html_writer::link($hotpot->index_url(), get_string('exit_index', 'hotpot'))),
  799. new html_table_cell(html_writer::link($hotpot->index_url(), get_string('exit_index_text', 'hotpot')))
  800. ));
  801. }
  802. if ($hotpot->exitoptions & hotpot::EXITOPTIONS_COURSE) {
  803. $table->data[] = new html_table_row(array(
  804. new html_table_cell(html_writer::link($hotpot->course_url(), get_string('exit_course', 'hotpot'))),
  805. new html_table_cell(html_writer::link($hotpot->course_url(), get_string('exit_course_text', 'hotpot')))
  806. ));
  807. }
  808. if ($hotpot->exitoptions & hotpot::EXITOPTIONS_GRADES) {
  809. if ($hotpot->course->showgrades && $hotpot->gradeweighting) {
  810. $url = new moodle_url($hotpot->grades_url());
  811. $table->data[] = new html_table_row(array(
  812. new html_table_cell(html_writer::link($url, get_string('exit_grades', 'hotpot'))),
  813. new html_table_cell(html_writer::link($url, get_string('exit_grades_text', 'hotpot')))
  814. ));
  815. }
  816. }
  817. $output = '';
  818. if ($count = count($table->data)) {
  819. if ($count>1) {
  820. $output .= $this->whatnext('exit_whatnext');
  821. }
  822. $output .= html_writer::table($table);
  823. }
  824. return $output;
  825. }
  826. }