PageRenderTime 62ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/mod/scorm/report/interactions/report.php

http://github.com/moodle/moodle
PHP | 609 lines | 508 code | 34 blank | 67 comment | 128 complexity | e2e6ac1aff51015955218066e7dbc6c2 MD5 | raw file
Possible License(s): MIT, AGPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-3.0, GPL-3.0, Apache-2.0, LGPL-2.1, BSD-3-Clause
  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. * Core Report class of basic reporting plugin
  18. * @package scormreport
  19. * @subpackage interactions
  20. * @author Dan Marsden and Ankit Kumar Agarwal
  21. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22. */
  23. defined('MOODLE_INTERNAL') || die();
  24. require_once($CFG->dirroot.'/mod/scorm/report/interactions/responsessettings_form.php');
  25. class scorm_interactions_report extends scorm_default_report {
  26. /**
  27. * displays the full report
  28. * @param stdClass $scorm full SCORM object
  29. * @param stdClass $cm - full course_module object
  30. * @param stdClass $course - full course object
  31. * @param string $download - type of download being requested
  32. */
  33. function display($scorm, $cm, $course, $download) {
  34. global $CFG, $DB, $OUTPUT, $PAGE;
  35. $contextmodule = get_context_instance(CONTEXT_MODULE, $cm->id);
  36. $action = optional_param('action', '', PARAM_ALPHA);
  37. $attemptids = optional_param_array('attemptid', array(), PARAM_RAW);
  38. $attemptsmode = optional_param('attemptsmode', SCORM_REPORT_ATTEMPTS_ALL_STUDENTS, PARAM_INT);
  39. $PAGE->set_url(new moodle_url($PAGE->url, array('attemptsmode' => $attemptsmode)));
  40. if ($action == 'delete' && has_capability('mod/scorm:deleteresponses', $contextmodule) && confirm_sesskey()) {
  41. if (scorm_delete_responses($attemptids, $scorm)) { //delete responses.
  42. add_to_log($course->id, 'scorm', 'delete attempts', 'report.php?id=' . $cm->id, implode(",", $attemptids), $cm->id);
  43. echo $OUTPUT->notification(get_string('scormresponsedeleted', 'scorm'), 'notifysuccess');
  44. }
  45. }
  46. // find out current groups mode
  47. $currentgroup = groups_get_activity_group($cm, true);
  48. // detailed report
  49. $mform = new mod_scorm_report_interactions_settings($PAGE->url, compact('currentgroup'));
  50. if ($fromform = $mform->get_data()) {
  51. $pagesize = $fromform->pagesize;
  52. $includeqtext = $fromform->qtext;
  53. $includeresp = $fromform->resp;
  54. $includeright = $fromform->right;
  55. set_user_preference('scorm_report_pagesize', $pagesize);
  56. set_user_preference('scorm_report_interactions_qtext', $includeqtext);
  57. set_user_preference('scorm_report_interactions_resp', $includeresp);
  58. set_user_preference('scorm_report_interactions_right', $includeright);
  59. } else {
  60. $pagesize = get_user_preferences('scorm_report_pagesize', 0);
  61. $includeqtext = get_user_preferences('scorm_report_interactions_qtext', 0);
  62. $includeresp = get_user_preferences('scorm_report_interactions_resp', 1);
  63. $includeright = get_user_preferences('scorm_report_interactions_right', 0);
  64. }
  65. if ($pagesize < 1) {
  66. $pagesize = SCORM_REPORT_DEFAULT_PAGE_SIZE;
  67. }
  68. // select group menu
  69. $displayoptions = array();
  70. $displayoptions['attemptsmode'] = $attemptsmode;
  71. $displayoptions['qtext'] = $includeqtext;
  72. $displayoptions['resp'] = $includeresp;
  73. $displayoptions['right'] = $includeright;
  74. $mform->set_data($displayoptions + array('pagesize' => $pagesize));
  75. if ($groupmode = groups_get_activity_groupmode($cm)) { // Groups are being used
  76. if (!$download) {
  77. groups_print_activity_menu($cm, new moodle_url($PAGE->url, $displayoptions));
  78. }
  79. }
  80. $formattextoptions = array('context' => get_context_instance(CONTEXT_COURSE, $course->id));
  81. // We only want to show the checkbox to delete attempts
  82. // if the user has permissions and if the report mode is showing attempts.
  83. $candelete = has_capability('mod/scorm:deleteresponses', $contextmodule)
  84. && ($attemptsmode != SCORM_REPORT_ATTEMPTS_STUDENTS_WITH_NO);
  85. // select the students
  86. $nostudents = false;
  87. if (empty($currentgroup)) {
  88. // all users who can attempt scoes
  89. if (!$students = get_users_by_capability($contextmodule, 'mod/scorm:savetrack', '', '', '', '', '', '', false)) {
  90. echo $OUTPUT->notification(get_string('nostudentsyet'));
  91. $nostudents = true;
  92. $allowedlist = '';
  93. } else {
  94. $allowedlist = array_keys($students);
  95. }
  96. } else {
  97. // all users who can attempt scoes and who are in the currently selected group
  98. if (!$groupstudents = get_users_by_capability($contextmodule, 'mod/scorm:savetrack', '', '', '', '', $currentgroup, '', false)) {
  99. echo $OUTPUT->notification(get_string('nostudentsingroup'));
  100. $nostudents = true;
  101. $groupstudents = array();
  102. }
  103. $allowedlist = array_keys($groupstudents);
  104. }
  105. if ( !$nostudents ) {
  106. // Now check if asked download of data
  107. $coursecontext = context_course::instance($course->id);
  108. if ($download) {
  109. $filename = clean_filename("$course->shortname ".format_string($scorm->name, true,$formattextoptions));
  110. }
  111. // Define table columns
  112. $columns = array();
  113. $headers = array();
  114. if (!$download && $candelete) {
  115. $columns[] = 'checkbox';
  116. $headers[] = null;
  117. }
  118. if (!$download && $CFG->grade_report_showuserimage) {
  119. $columns[] = 'picture';
  120. $headers[] = '';
  121. }
  122. $columns[] = 'fullname';
  123. $headers[] = get_string('name');
  124. $extrafields = get_extra_user_fields($coursecontext);
  125. foreach ($extrafields as $field) {
  126. $columns[] = $field;
  127. $headers[] = get_user_field_name($field);
  128. }
  129. $columns[] = 'attempt';
  130. $headers[] = get_string('attempt', 'scorm');
  131. $columns[] = 'start';
  132. $headers[] = get_string('started', 'scorm');
  133. $columns[] = 'finish';
  134. $headers[] = get_string('last', 'scorm');
  135. $columns[] = 'score';
  136. $headers[] = get_string('score', 'scorm');
  137. $scoes = $DB->get_records('scorm_scoes', array("scorm"=>$scorm->id), 'id');
  138. foreach ($scoes as $sco) {
  139. if ($sco->launch != '') {
  140. $columns[] = 'scograde'.$sco->id;
  141. $headers[] = format_string($sco->title,'',$formattextoptions);
  142. $table->head[]= format_string($sco->title,'',$formattextoptions);
  143. }
  144. }
  145. $params = array();
  146. list($usql, $params) = $DB->get_in_or_equal($allowedlist, SQL_PARAMS_NAMED);
  147. // Construct the SQL
  148. $select = 'SELECT DISTINCT '.$DB->sql_concat('u.id', '\'#\'', 'COALESCE(st.attempt, 0)').' AS uniqueid, ';
  149. $select .= 'st.scormid AS scormid, st.attempt AS attempt, ' .
  150. 'u.id AS userid, u.idnumber, u.firstname, u.lastname, u.picture, u.imagealt, u.email'.
  151. get_extra_user_fields_sql($coursecontext, 'u', '', array('idnumber')) . ' ';
  152. // This part is the same for all cases - join users and scorm_scoes_track tables
  153. $from = 'FROM {user} u ';
  154. $from .= 'LEFT JOIN {scorm_scoes_track} st ON st.userid = u.id AND st.scormid = '.$scorm->id;
  155. switch ($attemptsmode) {
  156. case SCORM_REPORT_ATTEMPTS_STUDENTS_WITH:
  157. // Show only students with attempts
  158. $where = ' WHERE u.id ' .$usql. ' AND st.userid IS NOT NULL';
  159. break;
  160. case SCORM_REPORT_ATTEMPTS_STUDENTS_WITH_NO:
  161. // Show only students without attempts
  162. $where = ' WHERE u.id ' .$usql. ' AND st.userid IS NULL';
  163. break;
  164. case SCORM_REPORT_ATTEMPTS_ALL_STUDENTS:
  165. // Show all students with or without attempts
  166. $where = ' WHERE u.id ' .$usql. ' AND (st.userid IS NOT NULL OR st.userid IS NULL)';
  167. break;
  168. }
  169. $countsql = 'SELECT COUNT(DISTINCT('.$DB->sql_concat('u.id', '\'#\'', 'COALESCE(st.attempt, 0)').')) AS nbresults, ';
  170. $countsql .= 'COUNT(DISTINCT('.$DB->sql_concat('u.id', '\'#\'', 'st.attempt').')) AS nbattempts, ';
  171. $countsql .= 'COUNT(DISTINCT(u.id)) AS nbusers ';
  172. $countsql .= $from.$where;
  173. $attempts = $DB->get_records_sql($select.$from.$where, $params);
  174. $questioncount = get_scorm_question_count($scorm->id);
  175. for($id = 0; $id < $questioncount; $id++) {
  176. if ($displayoptions['qtext']) {
  177. $columns[] = 'question' . $id;
  178. $headers[] = get_string('questionx', 'scormreport_interactions', $id);
  179. }
  180. if ($displayoptions['resp']) {
  181. $columns[] = 'response' . $id;
  182. $headers[] = get_string('responsex', 'scormreport_interactions', $id);
  183. }
  184. if ($displayoptions['right']) {
  185. $columns[] = 'right' . $id;
  186. $headers[] = get_string('rightanswerx', 'scormreport_interactions', $id);
  187. }
  188. }
  189. if (!$download) {
  190. $table = new flexible_table('mod-scorm-report');
  191. $table->define_columns($columns);
  192. $table->define_headers($headers);
  193. $table->define_baseurl($PAGE->url);
  194. $table->sortable(true);
  195. $table->collapsible(true);
  196. // This is done to prevent redundant data, when a user has multiple attempts
  197. $table->column_suppress('picture');
  198. $table->column_suppress('fullname');
  199. foreach ($extrafields as $field) {
  200. $table->column_suppress($field);
  201. }
  202. $table->no_sorting('start');
  203. $table->no_sorting('finish');
  204. $table->no_sorting('score');
  205. foreach ($scoes as $sco) {
  206. if ($sco->launch != '') {
  207. $table->no_sorting('scograde'.$sco->id);
  208. }
  209. }
  210. $table->column_class('picture', 'picture');
  211. $table->column_class('fullname', 'bold');
  212. $table->column_class('score', 'bold');
  213. $table->set_attribute('cellspacing', '0');
  214. $table->set_attribute('id', 'attempts');
  215. $table->set_attribute('class', 'generaltable generalbox');
  216. // Start working -- this is necessary as soon as the niceties are over
  217. $table->setup();
  218. } else if ($download == 'ODS') {
  219. require_once("$CFG->libdir/odslib.class.php");
  220. $filename .= ".ods";
  221. // Creating a workbook
  222. $workbook = new MoodleODSWorkbook("-");
  223. // Sending HTTP headers
  224. $workbook->send($filename);
  225. // Creating the first worksheet
  226. $sheettitle = get_string('report', 'scorm');
  227. $myxls =& $workbook->add_worksheet($sheettitle);
  228. // format types
  229. $format =& $workbook->add_format();
  230. $format->set_bold(0);
  231. $formatbc =& $workbook->add_format();
  232. $formatbc->set_bold(1);
  233. $formatbc->set_align('center');
  234. $formatb =& $workbook->add_format();
  235. $formatb->set_bold(1);
  236. $formaty =& $workbook->add_format();
  237. $formaty->set_bg_color('yellow');
  238. $formatc =& $workbook->add_format();
  239. $formatc->set_align('center');
  240. $formatr =& $workbook->add_format();
  241. $formatr->set_bold(1);
  242. $formatr->set_color('red');
  243. $formatr->set_align('center');
  244. $formatg =& $workbook->add_format();
  245. $formatg->set_bold(1);
  246. $formatg->set_color('green');
  247. $formatg->set_align('center');
  248. // Here starts workshhet headers
  249. $colnum = 0;
  250. foreach ($headers as $item) {
  251. $myxls->write(0, $colnum, $item, $formatbc);
  252. $colnum++;
  253. }
  254. $rownum = 1;
  255. } else if ($download =='Excel') {
  256. require_once("$CFG->libdir/excellib.class.php");
  257. $filename .= ".xls";
  258. // Creating a workbook
  259. $workbook = new MoodleExcelWorkbook("-");
  260. // Sending HTTP headers
  261. $workbook->send($filename);
  262. // Creating the first worksheet
  263. $sheettitle = get_string('report', 'scorm');
  264. $myxls =& $workbook->add_worksheet($sheettitle);
  265. // format types
  266. $format =& $workbook->add_format();
  267. $format->set_bold(0);
  268. $formatbc =& $workbook->add_format();
  269. $formatbc->set_bold(1);
  270. $formatbc->set_align('center');
  271. $formatb =& $workbook->add_format();
  272. $formatb->set_bold(1);
  273. $formaty =& $workbook->add_format();
  274. $formaty->set_bg_color('yellow');
  275. $formatc =& $workbook->add_format();
  276. $formatc->set_align('center');
  277. $formatr =& $workbook->add_format();
  278. $formatr->set_bold(1);
  279. $formatr->set_color('red');
  280. $formatr->set_align('center');
  281. $formatg =& $workbook->add_format();
  282. $formatg->set_bold(1);
  283. $formatg->set_color('green');
  284. $formatg->set_align('center');
  285. $colnum = 0;
  286. foreach ($headers as $item) {
  287. $myxls->write(0, $colnum, $item, $formatbc);
  288. $colnum++;
  289. }
  290. $rownum = 1;
  291. } else if ($download == 'CSV') {
  292. $filename .= ".txt";
  293. header("Content-Type: application/download\n");
  294. header("Content-Disposition: attachment; filename=\"$filename\"");
  295. header("Expires: 0");
  296. header("Cache-Control: must-revalidate,post-check=0,pre-check=0");
  297. header("Pragma: public");
  298. echo implode("\t", $headers)." \n";
  299. }
  300. if (!$download) {
  301. $sort = $table->get_sql_sort();
  302. } else {
  303. $sort = '';
  304. }
  305. // Fix some wired sorting
  306. if (empty($sort)) {
  307. $sort = ' ORDER BY uniqueid';
  308. } else {
  309. $sort = ' ORDER BY '.$sort;
  310. }
  311. if (!$download) {
  312. // Add extra limits due to initials bar
  313. list($twhere, $tparams) = $table->get_sql_where();
  314. if ($twhere) {
  315. $where .= ' AND '.$twhere; //initial bar
  316. $params = array_merge($params, $tparams);
  317. }
  318. if (!empty($countsql)) {
  319. $count = $DB->get_record_sql($countsql,$params);
  320. $totalinitials = $count->nbresults;
  321. if ($twhere) {
  322. $countsql .= ' AND '.$twhere;
  323. }
  324. $count = $DB->get_record_sql($countsql, $params);
  325. $total = $count->nbresults;
  326. }
  327. $table->pagesize($pagesize, $total);
  328. echo '<div class="quizattemptcounts">';
  329. if ( $count->nbresults == $count->nbattempts ) {
  330. echo get_string('reportcountattempts', 'scorm', $count);
  331. } else if ( $count->nbattempts>0 ) {
  332. echo get_string('reportcountallattempts', 'scorm', $count);
  333. } else {
  334. echo $count->nbusers.' '.get_string('users');
  335. }
  336. echo '</div>';
  337. }
  338. // Fetch the attempts
  339. if (!$download) {
  340. $attempts = $DB->get_records_sql($select.$from.$where.$sort, $params,
  341. $table->get_page_start(), $table->get_page_size());
  342. echo '<div id="scormtablecontainer">';
  343. if ($candelete) {
  344. // Start form
  345. $strreallydel = addslashes_js(get_string('deleteattemptcheck', 'scorm'));
  346. echo '<form id="attemptsform" method="post" action="' . $PAGE->url->out(false) .
  347. '" onsubmit="return confirm(\''.$strreallydel.'\');">';
  348. echo '<input type="hidden" name="action" value="delete"/>';
  349. echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
  350. echo '<div style="display: none;">';
  351. echo html_writer::input_hidden_params($PAGE->url);
  352. echo '</div>';
  353. echo '<div>';
  354. }
  355. $table->initialbars($totalinitials>20); // Build table rows
  356. } else {
  357. $attempts = $DB->get_records_sql($select.$from.$where.$sort, $params);
  358. }
  359. if ($attempts) {
  360. foreach ($attempts as $scouser) {
  361. $row = array();
  362. if (!empty($scouser->attempt)) {
  363. $timetracks = scorm_get_sco_runtime($scorm->id, false, $scouser->userid, $scouser->attempt);
  364. } else {
  365. $timetracks = '';
  366. }
  367. if (in_array('checkbox', $columns)) {
  368. if ($candelete && !empty($timetracks->start)) {
  369. $row[] = '<input type="checkbox" name="attemptid[]" value="'. $scouser->userid . ':' . $scouser->attempt . '" />';
  370. } else if ($candelete) {
  371. $row[] = '';
  372. }
  373. }
  374. if (in_array('picture', $columns)) {
  375. $user = (object)array(
  376. 'id'=>$scouser->userid,
  377. 'picture'=>$scouser->picture,
  378. 'imagealt'=>$scouser->imagealt,
  379. 'email'=>$scouser->email,
  380. 'firstname'=>$scouser->firstname,
  381. 'lastname'=>$scouser->lastname);
  382. $row[] = $OUTPUT->user_picture($user, array('courseid'=>$course->id));
  383. }
  384. if (!$download) {
  385. $row[] = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$scouser->userid.'&amp;course='.$course->id.'">'.fullname($scouser).'</a>';
  386. } else {
  387. $row[] = fullname($scouser);
  388. }
  389. foreach ($extrafields as $field) {
  390. $row[] = s($scouser->{$field});
  391. }
  392. if (empty($timetracks->start)) {
  393. $row[] = '-';
  394. $row[] = '-';
  395. $row[] = '-';
  396. $row[] = '-';
  397. } else {
  398. if (!$download) {
  399. $row[] = '<a href="userreport.php?a='.$scorm->id.'&amp;user='.$scouser->userid.'&amp;attempt='.$scouser->attempt.'">'.$scouser->attempt.'</a>';
  400. } else {
  401. $row[] = $scouser->attempt;
  402. }
  403. if ($download =='ODS' || $download =='Excel' ) {
  404. $row[] = userdate($timetracks->start, get_string("strftimedatetime", "langconfig"));
  405. } else {
  406. $row[] = userdate($timetracks->start);
  407. }
  408. if ($download =='ODS' || $download =='Excel' ) {
  409. $row[] = userdate($timetracks->finish, get_string('strftimedatetime', 'langconfig'));
  410. } else {
  411. $row[] = userdate($timetracks->finish);
  412. }
  413. $row[] = scorm_grade_user_attempt($scorm, $scouser->userid, $scouser->attempt);
  414. }
  415. // print out all scores of attempt
  416. foreach ($scoes as $sco) {
  417. if ($sco->launch != '') {
  418. if ($trackdata = scorm_get_tracks($sco->id, $scouser->userid, $scouser->attempt)) {
  419. if ($trackdata->status == '') {
  420. $trackdata->status = 'notattempted';
  421. }
  422. $strstatus = get_string($trackdata->status, 'scorm');
  423. // if raw score exists, print it
  424. if ($trackdata->score_raw != '') {
  425. $score = $trackdata->score_raw;
  426. // add max score if it exists
  427. if ($scorm->version == 'SCORM_1.3') {
  428. $maxkey = 'cmi.score.max';
  429. } else {
  430. $maxkey = 'cmi.core.score.max';
  431. }
  432. if (isset($trackdata->$maxkey)) {
  433. $score .= '/'.$trackdata->$maxkey;
  434. }
  435. // else print out status
  436. } else {
  437. $score = $strstatus;
  438. }
  439. if (!$download) {
  440. $row[] = '<img src="'.$OUTPUT->pix_url($trackdata->status, 'scorm').'" alt="'.$strstatus.'" title="'.$strstatus.'" /><br/>
  441. <a href="userreport.php?b='.$sco->id.'&amp;user='.$scouser->userid.'&amp;attempt='.$scouser->attempt.
  442. '" title="'.get_string('details', 'scorm').'">'.$score.'</a>';
  443. } else {
  444. $row[] = $score;
  445. }
  446. // interaction data
  447. $i=0;
  448. $element='cmi.interactions_'.$i.'.id';
  449. while(isset($trackdata->$element)) {
  450. if ($displayoptions['qtext']) {
  451. $element='cmi.interactions_'.$i.'.id';
  452. if (isset($trackdata->$element)) {
  453. $row[] = s($trackdata->$element);
  454. } else {
  455. $row[] = '&nbsp;';
  456. }
  457. }
  458. if ($displayoptions['resp']) {
  459. $element='cmi.interactions_'.$i.'.student_response';
  460. if (isset($trackdata->$element)) {
  461. $row[] = s($trackdata->$element);
  462. } else {
  463. $row[] = '&nbsp;';
  464. }
  465. }
  466. if ($displayoptions['right']) {
  467. $j=0;
  468. $element = 'cmi.interactions_'.$i.'.correct_responses_'.$j.'.pattern';
  469. $rightans = '';
  470. if (isset($trackdata->$element)) {
  471. while(isset($trackdata->$element)) {
  472. if($j>0) {
  473. $rightans .= ',';
  474. }
  475. $rightans .= s($trackdata->$element);
  476. $j++;
  477. $element = 'cmi.interactions_'.$i.'.correct_responses_'.$j.'.pattern';
  478. }
  479. $row[] = $rightans;
  480. } else {
  481. $row[] = '&nbsp;';
  482. }
  483. }
  484. $i++;
  485. $element = 'cmi.interactions_'.$i.'.id';
  486. }
  487. //---end of interaction data*/
  488. } else {
  489. // if we don't have track data, we haven't attempted yet
  490. $strstatus = get_string('notattempted', 'scorm');
  491. if (!$download) {
  492. $row[] = '<img src="'.$OUTPUT->pix_url('notattempted', 'scorm').'" alt="'.$strstatus.'" title="'.$strstatus.'" /><br/>'.$strstatus;
  493. } else {
  494. $row[] = $strstatus;
  495. }
  496. }
  497. }
  498. }
  499. if (!$download) {
  500. $table->add_data($row);
  501. } else if ($download == 'Excel' or $download == 'ODS') {
  502. $colnum = 0;
  503. foreach ($row as $item) {
  504. $myxls->write($rownum, $colnum, $item, $format);
  505. $colnum++;
  506. }
  507. $rownum++;
  508. } else if ($download == 'CSV') {
  509. $text = implode("\t", $row);
  510. echo $text." \n";
  511. }
  512. }
  513. if (!$download) {
  514. $table->finish_output();
  515. if ($candelete) {
  516. echo '<table id="commands">';
  517. echo '<tr><td>';
  518. echo '<a href="javascript:select_all_in(\'DIV\', null, \'scormtablecontainer\');">'.
  519. get_string('selectall', 'scorm').'</a> / ';
  520. echo '<a href="javascript:deselect_all_in(\'DIV\', null, \'scormtablecontainer\');">'.
  521. get_string('selectnone', 'scorm').'</a> ';
  522. echo '&nbsp;&nbsp;';
  523. echo '<input type="submit" value="'.get_string('deleteselected', 'quiz_overview').'"/>';
  524. echo '</td></tr></table>';
  525. // Close form
  526. echo '</div>';
  527. echo '</form>';
  528. }
  529. echo '</div>';
  530. if (!empty($attempts)) {
  531. echo '<table class="boxaligncenter"><tr>';
  532. echo '<td>';
  533. echo $OUTPUT->single_button(new moodle_url($PAGE->url,
  534. array('download'=>'ODS') + $displayoptions),
  535. get_string('downloadods'));
  536. echo "</td>\n";
  537. echo '<td>';
  538. echo $OUTPUT->single_button(new moodle_url($PAGE->url,
  539. array('download'=>'Excel') + $displayoptions),
  540. get_string('downloadexcel'));
  541. echo "</td>\n";
  542. echo '<td>';
  543. echo $OUTPUT->single_button(new moodle_url($PAGE->url,
  544. array('download'=>'CSV') + $displayoptions),
  545. get_string('downloadtext'));
  546. echo "</td>\n";
  547. echo "<td>";
  548. echo "</td>\n";
  549. echo '</tr></table>';
  550. }
  551. }
  552. } else {
  553. if ($candelete && !$download) {
  554. echo '</div>';
  555. echo '</form>';
  556. $table->finish_output();
  557. }
  558. echo '</div>';
  559. }
  560. // Show preferences form irrespective of attempts are there to report or not
  561. if (!$download) {
  562. $mform->set_data(compact('detailedrep', 'pagesize', 'attemptsmode'));
  563. $mform->display();
  564. }
  565. if ($download == 'Excel' or $download == 'ODS') {
  566. $workbook->close();
  567. exit;
  568. } else if ($download == 'CSV') {
  569. exit;
  570. }
  571. } else {
  572. echo $OUTPUT->notification(get_string('noactivity', 'scorm'));
  573. }
  574. }// function ends
  575. }