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