Differences Between: [Versions 310 and 400] [Versions 311 and 400] [Versions 39 and 400] [Versions 400 and 401] [Versions 400 and 402] [Versions 400 and 403]
1 <?php 2 3 // This file is part of Moodle - http://moodle.org/ 4 // 5 // Moodle is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // Moodle is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 17 18 /** 19 * Displays the lesson statistics. 20 * 21 * @package mod_lesson 22 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late 24 **/ 25 26 require_once('../../config.php'); 27 require_once($CFG->dirroot.'/mod/lesson/locallib.php'); 28 29 $id = required_param('id', PARAM_INT); // Course Module ID 30 $pageid = optional_param('pageid', null, PARAM_INT); // Lesson Page ID 31 $action = optional_param('action', 'reportoverview', PARAM_ALPHA); // action to take 32 $nothingtodisplay = false; 33 34 $cm = get_coursemodule_from_id('lesson', $id, 0, false, MUST_EXIST); 35 $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); 36 $lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST)); 37 38 require_login($course, false, $cm); 39 40 $currentgroup = groups_get_activity_group($cm, true); 41 42 $context = context_module::instance($cm->id); 43 require_capability('mod/lesson:viewreports', $context); 44 45 $url = new moodle_url('/mod/lesson/report.php', array('id'=>$id)); 46 $url->param('action', $action); 47 if ($pageid !== null) { 48 $url->param('pageid', $pageid); 49 } 50 $PAGE->set_url($url); 51 if ($action == 'reportdetail') { 52 $PAGE->navbar->add(get_string('report', 'lesson'), $url); 53 } 54 55 $lessonoutput = $PAGE->get_renderer('mod_lesson'); 56 $PAGE->activityheader->set_description(''); 57 $reportactionmenu = new \mod_lesson\output\report_action_menu($id, $url); 58 $reportactionarea = $lessonoutput->render($reportactionmenu); 59 60 if ($action === 'delete') { 61 /// Process any form data before fetching attempts, grades and times 62 if (has_capability('mod/lesson:edit', $context) and $form = data_submitted() and confirm_sesskey()) { 63 /// Cycle through array of userids with nested arrays of tries 64 if (!empty($form->attempts)) { 65 foreach ($form->attempts as $userid => $tries) { 66 // Modifier IS VERY IMPORTANT! What does it do? 67 // Well, it is for when you delete multiple attempts for the same user. 68 // If you delete try 1 and 3 for a user, then after deleting try 1, try 3 then 69 // becomes try 2 (because try 1 is gone and all tries after try 1 get decremented). 70 // So, the modifier makes sure that the submitted try refers to the current try in the 71 // database - hope this all makes sense :) 72 $modifier = 0; 73 74 foreach ($tries as $try => $junk) { 75 $try -= $modifier; 76 77 /// Clean up the timer table by removing using the order - this is silly, it should be linked to specific attempt (skodak) 78 $timers = $lesson->get_user_timers($userid, 'starttime', 'id', $try, 1); 79 if ($timers) { 80 $timer = reset($timers); 81 $DB->delete_records('lesson_timer', array('id' => $timer->id)); 82 } 83 84 $params = array ("userid" => $userid, "lessonid" => $lesson->id); 85 // Remove the grade from the grades tables - this is silly, it should be linked to specific attempt (skodak). 86 $grades = $DB->get_records_sql("SELECT id FROM {lesson_grades} 87 WHERE userid = :userid AND lessonid = :lessonid 88 ORDER BY completed", $params, $try, 1); 89 90 if ($grades) { 91 $grade = reset($grades); 92 $DB->delete_records('lesson_grades', array('id' => $grade->id)); 93 } 94 95 /// Remove attempts and update the retry number 96 $DB->delete_records('lesson_attempts', array('userid' => $userid, 'lessonid' => $lesson->id, 'retry' => $try)); 97 $DB->execute("UPDATE {lesson_attempts} SET retry = retry - 1 WHERE userid = ? AND lessonid = ? AND retry > ?", array($userid, $lesson->id, $try)); 98 99 /// Remove seen branches and update the retry number 100 $DB->delete_records('lesson_branch', array('userid' => $userid, 'lessonid' => $lesson->id, 'retry' => $try)); 101 $DB->execute("UPDATE {lesson_branch} SET retry = retry - 1 WHERE userid = ? AND lessonid = ? AND retry > ?", array($userid, $lesson->id, $try)); 102 103 /// update central gradebook 104 lesson_update_grades($lesson, $userid); 105 106 $modifier++; 107 } 108 } 109 } 110 } 111 redirect(new moodle_url($PAGE->url, array('action'=>'reportoverview'))); 112 113 } else if ($action === 'reportoverview') { 114 /************************************************************************** 115 this action is for default view and overview view 116 **************************************************************************/ 117 118 // Get the table and data for build statistics. 119 list($table, $data) = lesson_get_overview_report_table_and_data($lesson, $currentgroup); 120 121 if ($table === false) { 122 echo $lessonoutput->header($lesson, $cm, $action, false, null, get_string('nolessonattempts', 'lesson')); 123 if ($PAGE->has_secondary_navigation()) { 124 echo $reportactionarea; 125 } 126 if (!empty($currentgroup)) { 127 $groupname = groups_get_group_name($currentgroup); 128 echo $OUTPUT->notification(get_string('nolessonattemptsgroup', 'lesson', $groupname)); 129 } else { 130 echo $OUTPUT->notification(get_string('nolessonattempts', 'lesson')); 131 } 132 groups_print_activity_menu($cm, $url); 133 echo $OUTPUT->footer(); 134 exit(); 135 } 136 137 echo $lessonoutput->header($lesson, $cm, $action, false, null, get_string('overview', 'lesson')); 138 if ($PAGE->has_secondary_navigation()) { 139 echo $reportactionarea; 140 } 141 groups_print_activity_menu($cm, $url); 142 143 $course_context = context_course::instance($course->id); 144 if (has_capability('gradereport/grader:view', $course_context) && has_capability('moodle/grade:viewall', $course_context)) { 145 $seeallgradeslink = new moodle_url('/grade/report/grader/index.php', array('id'=>$course->id)); 146 $seeallgradeslink = html_writer::link($seeallgradeslink, get_string('seeallcoursegrades', 'grades')); 147 echo $OUTPUT->box($seeallgradeslink, 'allcoursegrades'); 148 } 149 150 // The attempts table. 151 $attemptstable = html_writer::table($table); 152 153 // The HTML that we will be displaying which includes the attempts table and bulk actions menu, if necessary. 154 $attemptshtml = $attemptstable; 155 156 // Show bulk actions when user has capability to edit the lesson. 157 if (has_capability('mod/lesson:edit', $context)) { 158 $reporturl = new moodle_url('/mod/lesson/report.php'); 159 $formid = 'mod-lesson-report-form'; 160 161 // Sesskey hidden input. 162 $formcontents = html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()]); 163 164 // CMID hidden input. 165 $formcontents .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'id', 'value' => $cm->id]); 166 167 // Attempts table. 168 $formcontents .= $attemptstable; 169 170 // Bulk actions menu. 171 $attemptsactions = [ 172 'delete' => get_string('deleteselected') 173 ]; 174 $bulkactions = new single_select($reporturl, 'action', $attemptsactions, '', ['' => 'choosedots'], $formid); 175 $bulkactions->set_label(get_string('withselectedattempts', 'lesson')); 176 $bulkactions->disabled = true; 177 $bulkactions->attributes = [ 178 'data-action' => 'toggle', 179 'data-togglegroup' => 'lesson-attempts', 180 'data-toggle' => 'action', 181 ]; 182 $bulkactionshtml = $OUTPUT->render($bulkactions); 183 $formcontents .= $OUTPUT->box($bulkactionshtml, 'center'); 184 185 // Build the attempts form. 186 $formattributes = [ 187 'id' => $formid, 188 'method' => 'post', 189 ]; 190 $attemptshtml = html_writer::tag('form', $formcontents, $formattributes); 191 } 192 193 // Show the attempts HTML. 194 echo $attemptshtml; 195 196 // Calculate the Statistics. 197 if ($data->avetime == null) { 198 $data->avetime = get_string("notcompleted", "lesson"); 199 } else { 200 $data->avetime = format_float($data->avetime / $data->numofattempts, 0); 201 $data->avetime = format_time($data->avetime); 202 } 203 if ($data->hightime == null) { 204 $data->hightime = get_string("notcompleted", "lesson"); 205 } else { 206 $data->hightime = format_time($data->hightime); 207 } 208 if ($data->lowtime == null) { 209 $data->lowtime = get_string("notcompleted", "lesson"); 210 } else { 211 $data->lowtime = format_time($data->lowtime); 212 } 213 214 if ($data->lessonscored) { 215 if ($data->numofattempts == 0) { 216 $data->avescore = get_string("notcompleted", "lesson"); 217 } else { 218 $data->avescore = format_float($data->avescore, 2) . '%'; 219 } 220 if ($data->highscore === null) { 221 $data->highscore = get_string("notcompleted", "lesson"); 222 } else { 223 $data->highscore .= '%'; 224 } 225 if ($data->lowscore === null) { 226 $data->lowscore = get_string("notcompleted", "lesson"); 227 } else { 228 $data->lowscore .= '%'; 229 } 230 231 // Display the full stats for the lesson. 232 echo $OUTPUT->heading(get_string('lessonstats', 'lesson'), 3); 233 $stattable = new html_table(); 234 $stattable->head = array(get_string('averagescore', 'lesson'), get_string('averagetime', 'lesson'), 235 get_string('highscore', 'lesson'), get_string('lowscore', 'lesson'), 236 get_string('hightime', 'lesson'), get_string('lowtime', 'lesson')); 237 $stattable->align = array('center', 'center', 'center', 'center', 'center', 'center'); 238 $stattable->attributes['class'] = 'standardtable generaltable'; 239 $stattable->data[] = array($data->avescore, $data->avetime, $data->highscore, $data->lowscore, $data->hightime, $data->lowtime); 240 241 } else { 242 // Display simple stats for the lesson. 243 echo $OUTPUT->heading(get_string('lessonstats', 'lesson'), 3); 244 $stattable = new html_table(); 245 $stattable->head = array(get_string('averagetime', 'lesson'), get_string('hightime', 'lesson'), 246 get_string('lowtime', 'lesson')); 247 $stattable->align = array('center', 'center', 'center'); 248 $stattable->attributes['class'] = 'standardtable generaltable'; 249 $stattable->data[] = array($data->avetime, $data->hightime, $data->lowtime); 250 } 251 252 echo html_writer::table($stattable); 253 } else if ($action === 'reportdetail') { 254 /************************************************************************** 255 this action is for a student detailed view and for the general detailed view 256 257 General flow of this section of the code 258 1. Generate a object which holds values for the statistics for each question/answer 259 2. Cycle through all the pages to create a object. Foreach page, see if the student actually answered 260 the page. Then process the page appropriatly. Display all info about the question, 261 Highlight correct answers, show how the user answered the question, and display statistics 262 about each page 263 3. Print out info about the try (if needed) 264 4. Print out the object which contains all the try info 265 266 **************************************************************************/ 267 echo $lessonoutput->header($lesson, $cm, $action, false, null, get_string('detailedstats', 'lesson')); 268 if ($PAGE->has_secondary_navigation()) { 269 echo $reportactionarea; 270 } 271 groups_print_activity_menu($cm, $url); 272 273 $course_context = context_course::instance($course->id); 274 if (has_capability('gradereport/grader:view', $course_context) && has_capability('moodle/grade:viewall', $course_context)) { 275 $seeallgradeslink = new moodle_url('/grade/report/grader/index.php', array('id'=>$course->id)); 276 $seeallgradeslink = html_writer::link($seeallgradeslink, get_string('seeallcoursegrades', 'grades')); 277 echo $OUTPUT->box($seeallgradeslink, 'allcoursegrades'); 278 } 279 280 $formattextdefoptions = new stdClass; 281 $formattextdefoptions->para = false; //I'll use it widely in this page 282 $formattextdefoptions->overflowdiv = true; 283 284 $userid = optional_param('userid', null, PARAM_INT); // if empty, then will display the general detailed view 285 $try = optional_param('try', null, PARAM_INT); 286 287 list($answerpages, $userstats) = lesson_get_user_detailed_report_data($lesson, $userid, $try); 288 289 /// actually start printing something 290 $table = new html_table(); 291 $table->wrap = array(); 292 $table->width = "60%"; 293 if (!empty($userid)) { 294 // if looking at a students try, print out some basic stats at the top 295 296 // print out users name 297 //$headingobject->lastname = $students[$userid]->lastname; 298 //$headingobject->firstname = $students[$userid]->firstname; 299 //$headingobject->attempt = $try + 1; 300 //print_heading(get_string("studentattemptlesson", "lesson", $headingobject)); 301 echo $OUTPUT->heading(get_string('attempt', 'lesson', $try+1), 3); 302 303 $table->head = array(); 304 $table->align = array('right', 'left'); 305 $table->attributes['class'] = 'table table-striped'; 306 307 if (empty($userstats->gradeinfo)) { 308 $table->align = array("center"); 309 310 $table->data[] = array(get_string("notcompleted", "lesson")); 311 } else { 312 $user = $DB->get_record('user', array('id' => $userid)); 313 314 $gradeinfo = lesson_grade($lesson, $try, $user->id); 315 316 $table->data[] = array(get_string('name').':', $OUTPUT->user_picture($user, array('courseid'=>$course->id)).fullname($user, true)); 317 $table->data[] = array(get_string("timetaken", "lesson").":", format_time($userstats->timetotake)); 318 $table->data[] = array(get_string("completed", "lesson").":", userdate($userstats->completed)); 319 $table->data[] = array(get_string('rawgrade', 'lesson').':', $userstats->gradeinfo->earned.'/'.$userstats->gradeinfo->total); 320 $table->data[] = array(get_string("grade", "lesson").":", $userstats->grade."%"); 321 } 322 echo html_writer::table($table); 323 324 // Don't want this class for later tables 325 $table->attributes['class'] = ''; 326 } 327 328 foreach ($answerpages as $page) { 329 $table->align = array('left', 'left'); 330 $table->size = array('70%', null); 331 $table->attributes['class'] = 'table table-striped'; 332 unset($table->data); 333 if ($page->grayout) { // set the color of text 334 $fontstart = html_writer::start_tag('span', array('class' => 'dimmed_text')); 335 $fontend = html_writer::end_tag('span'); 336 $fontstart2 = $fontstart; 337 $fontend2 = $fontend; 338 } else { 339 $fontstart = ''; 340 $fontend = ''; 341 $fontstart2 = ''; 342 $fontend2 = ''; 343 } 344 345 $table->head = array($fontstart2.$page->qtype.": ".format_string($page->title).$fontend2, $fontstart2.get_string("classstats", "lesson").$fontend2); 346 $table->data[] = array($fontstart.get_string("question", "lesson").": <br />".$fontend.$fontstart2.$page->contents.$fontend2, " "); 347 $table->data[] = array($fontstart.get_string("answer", "lesson").":".$fontend, ' '); 348 // apply the font to each answer 349 if (!empty($page->answerdata) && !empty($page->answerdata->answers)) { 350 foreach ($page->answerdata->answers as $answer){ 351 $modified = array(); 352 foreach ($answer as $single) { 353 // need to apply a font to each one 354 $modified[] = $fontstart2.$single.$fontend2; 355 } 356 $table->data[] = $modified; 357 } 358 if (isset($page->answerdata->response)) { 359 $table->data[] = array($fontstart.get_string("response", "lesson").": <br />".$fontend 360 .$fontstart2.$page->answerdata->response.$fontend2, " "); 361 } 362 $table->data[] = array($page->answerdata->score, " "); 363 } else { 364 $table->data[] = array(get_string('didnotanswerquestion', 'lesson'), " "); 365 } 366 echo html_writer::table($table); 367 } 368 } else { 369 print_error('unknowaction'); 370 } 371 372 /// Finish the page 373 echo $OUTPUT->footer();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body