diff --git a/course/user.php b/course/user.php
index c257dcecea7..c7b9e309901 100644
--- a/course/user.php
+++ b/course/user.php
@@ -24,46 +24,34 @@
require_once("../config.php");
require_once("lib.php");
-require_once($CFG->libdir.'/completionlib.php');
$id = required_param('id',PARAM_INT); // course id
$user = required_param('user',PARAM_INT); // user id
$mode = optional_param('mode', "todaylogs", PARAM_ALPHA);
-$page = optional_param('page', 0, PARAM_INT);
-$perpage = optional_param('perpage', 100, PARAM_INT);
$url = new moodle_url('/course/user.php', array('id'=>$id,'user'=>$user, 'mode'=>$mode));
-if ($page !== 0) {
- $url->param('page', $page);
-}
-if ($perpage !== 100) {
- $url->param('perpage', $perpage);
-}
-$PAGE->set_url($url);
-if (!$course = $DB->get_record('course', array('id'=>$id))) {
- print_error('invalidcourseid', 'error');
-}
-
-if (! $user = $DB->get_record("user", array("id"=>$user))) {
- print_error('invaliduserid', 'error');
-}
+$course = $DB->get_record('course', array('id'=>$id), '*', MUST_EXIST);
+$user = $DB->get_record("user", array("id"=>$user, 'deleted'=>0), '*', MUST_EXIST);
if ($mode === 'outline' or $mode === 'complete') {
$url = new moodle_url('/report/outline/user.php', array('id'=>$user->id, 'course'=>$course->id, 'mode'=>$mode));
redirect($url);
-
-} else if ($mode === 'todaylogs' or $mode === 'alllogs') {
+}
+if ($mode === 'todaylogs' or $mode === 'alllogs') {
$logmode = ($mode === 'todaylogs') ? 'today' : 'all';
$url = new moodle_url('/report/log/user.php', array('id'=>$user->id, 'course'=>$course->id, 'mode'=>$logmode));
redirect($url);
-} else if ($mode === 'stats') {
+}
+if ($mode === 'stats') {
$url = new moodle_url('/report/stats/user.php', array('id'=>$user->id, 'course'=>$course->id));
redirect($url);
}
+if ($mode === 'coursecompletions' or $mode === 'coursecompletion') {
+ $url = new moodle_url('/report/completion/user.php', array('id'=>$user->id, 'course'=>$course->id));
+ redirect($url);
+}
-
-require_login();
$coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
$personalcontext = get_context_instance(CONTEXT_USER, $user->id);
@@ -83,8 +71,6 @@ if ($user->deleted) {
die;
}
-//TODO: all this is a hack - we can not link to plugins like this - all this must be abstracted to plugin callbacks!
-
// prepare list of allowed modes
$myreports = ($course->showreports and $USER->id == $user->id);
$anyreport = has_capability('moodle/user:viewuseractivitiesreport', $personalcontext);
@@ -108,19 +94,6 @@ if (has_capability('moodle/grade:viewall', $coursecontext)) {
$modes[] = 'grade';
}
-// Course completion tab
-if (!empty($CFG->enablecompletion) && ($course->id == SITEID || !empty($course->enablecompletion)) && // completion enabled
- ($myreports || $anyreport || ($course->id == SITEID || has_capability('report/completion:view', $coursecontext)))) { // permissions to view the report
-
- // Decide if singular or plural
- if ($course->id == SITEID) {
- $modes[] = 'coursecompletions';
- } else {
- $modes[] = 'coursecompletion';
- }
-}
-
-
if (empty($modes)) {
require_capability('moodle/user:viewuseractivitiesreport', $personalcontext);
}
@@ -133,15 +106,6 @@ if (!in_array($mode, $modes)) {
add_to_log($course->id, "course", "user report", "user.php?id=$course->id&user=$user->id&mode=$mode", "$user->id");
$stractivityreport = get_string("activityreport");
-$strparticipants = get_string("participants");
-$strcomplete = get_string("complete");
-$strmode = get_string($mode);
-$fullname = fullname($user, true);
-
-$link = null;
-if ($course->id != SITEID && has_capability('moodle/course:viewparticipants', $coursecontext)) {
- $link = new moodle_url('/user/index.php', array('id'=>$course->id));
-}
$PAGE->navigation->extend_for_user($user);
$PAGE->navigation->set_userid_for_parent_checks($user->id); // see MDL-25805 for reasons and for full commit reference for reversal when fixed.
@@ -164,245 +128,6 @@ switch ($mode) {
}
break;
- case "coursecompletion":
- case "coursecompletions":
-
- // Display course completion user report
-
- // Grab all courses the user is enrolled in and their completion status
- $sql = "
- SELECT DISTINCT
- c.id AS id
- FROM
- {course} c
- INNER JOIN
- {context} con
- ON con.instanceid = c.id
- INNER JOIN
- {role_assignments} ra
- ON ra.contextid = con.id
- INNER JOIN
- {enrol} e
- ON c.id = e.courseid
- INNER JOIN
- {user_enrolments} ue
- ON e.id = ue.enrolid AND ra.userid = ue.userid
- AND ra.userid = {$user->id}
- ";
-
- // Get roles that are tracked by course completion
- if ($roles = $CFG->gradebookroles) {
- $sql .= '
- AND ra.roleid IN ('.$roles.')
- ';
- }
-
- $sql .= '
- WHERE
- con.contextlevel = '.CONTEXT_COURSE.'
- AND c.enablecompletion = 1
- ';
-
-
- // If we are looking at a specific course
- if ($course->id != 1) {
- $sql .= '
- AND c.id = '.(int)$course->id.'
- ';
- }
-
- // Check if result is empty
- $rs = $DB->get_recordset_sql($sql);
- if (!$rs->valid()) {
-
- if ($course->id != 1) {
- $error = get_string('nocompletions', 'report_completion');
- } else {
- $error = get_string('nocompletioncoursesenroled', 'report_completion');
- }
-
- echo $OUTPUT->notification($error);
- $rs->close(); // not going to loop (but break), close rs
- break;
- }
-
- // Categorize courses by their status
- $courses = array(
- 'inprogress' => array(),
- 'complete' => array(),
- 'unstarted' => array()
- );
-
- // Sort courses by the user's status in each
- foreach ($rs as $course_completion) {
- $c_info = new completion_info((object)$course_completion);
-
- // Is course complete?
- $coursecomplete = $c_info->is_course_complete($user->id);
-
- // Has this user completed any criteria?
- $criteriacomplete = $c_info->count_course_user_data($user->id);
-
- if ($coursecomplete) {
- $courses['complete'][] = $c_info;
- } else if ($criteriacomplete) {
- $courses['inprogress'][] = $c_info;
- } else {
- $courses['unstarted'][] = $c_info;
- }
- }
- $rs->close(); // after loop, close rs
-
- // Loop through course status groups
- foreach ($courses as $type => $infos) {
-
- // If there are courses with this status
- if (!empty($infos)) {
-
- echo '
'.get_string($type, 'report_completion').'
';
- echo '';
- echo '';
-
- // For each course
- foreach ($infos as $c_info) {
-
- // Get course info
- $c_course = $DB->get_record('course', array('id' => $c_info->course_id));
- $course_context = get_context_instance(CONTEXT_COURSE, $c_course->id, MUST_EXIST);
- $course_name = format_string($c_course->fullname, true, array('context' => $course_context));
-
- // Get completions
- $completions = $c_info->get_completions($user->id);
-
- // Save row data
- $rows = array();
-
- // For aggregating activity completion
- $activities = array();
- $activities_complete = 0;
-
- // For aggregating prerequisites
- $prerequisites = array();
- $prerequisites_complete = 0;
-
- // Loop through course criteria
- foreach ($completions as $completion) {
- $criteria = $completion->get_criteria();
- $complete = $completion->is_complete();
-
- // Activities are a special case, so cache them and leave them till last
- if ($criteria->criteriatype == COMPLETION_CRITERIA_TYPE_ACTIVITY) {
- $activities[$criteria->moduleinstance] = $complete;
-
- if ($complete) {
- $activities_complete++;
- }
-
- continue;
- }
-
- // Prerequisites are also a special case, so cache them and leave them till last
- if ($criteria->criteriatype == COMPLETION_CRITERIA_TYPE_COURSE) {
- $prerequisites[$criteria->courseinstance] = $complete;
-
- if ($complete) {
- $prerequisites_complete++;
- }
-
- continue;
- }
-
- $row = array();
- $row['title'] = $criteria->get_title();
- $row['status'] = $completion->get_status();
- $rows[] = $row;
- }
-
- // Aggregate activities
- if (!empty($activities)) {
-
- $row = array();
- $row['title'] = get_string('activitiescomplete', 'report_completion');
- $row['status'] = $activities_complete.' of '.count($activities);
- $rows[] = $row;
- }
-
- // Aggregate prerequisites
- if (!empty($prerequisites)) {
-
- $row = array();
- $row['title'] = get_string('prerequisitescompleted', 'completion');
- $row['status'] = $prerequisites_complete.' of '.count($prerequisites);
- array_splice($rows, 0, 0, array($row));
- }
-
- $first_row = true;
-
- // Print table
- foreach ($rows as $row) {
-
- // Display course name on first row
- if ($first_row) {
- echo '| '.$course_name.' | ';
- } else {
- echo '
| ';
- }
-
- echo '';
- echo $row['title'];
- echo ' | ';
-
- switch ($row['status']) {
- case 'Yes':
- echo get_string('complete');
- break;
-
- case 'No':
- echo get_string('incomplete', 'report_completion');
- break;
-
- default:
- echo $row['status'];
- }
-
- // Display link on first row
- echo ' | ';
- if ($first_row) {
- echo ''.get_string('detailedview', 'report_completion').'';
- }
- echo ' | ';
-
- // Display completion date for completed courses on first row
- if ($type === 'complete' && $first_row) {
- $params = array(
- 'userid' => $user->id,
- 'course' => $c_course->id
- );
-
- $ccompletion = new completion_completion($params);
- echo ''.userdate($ccompletion->timecompleted, '%e %B %G').' | ';
- }
-
- $first_row = false;
- echo '
';
- }
- }
-
- echo '
';
- }
-
- }
-
break;
default:
// can not be reached ;-)
diff --git a/report/completion/lib.php b/report/completion/lib.php
index 3bb40de9e80..12efc71bbdf 100644
--- a/report/completion/lib.php
+++ b/report/completion/lib.php
@@ -33,7 +33,7 @@ defined('MOODLE_INTERNAL') || die;
* @param stdClass $context The context of the course
*/
function report_completion_extend_navigation_course($navigation, $course, $context) {
- global $CFG, $OUTPUT;
+ global $CFG;
require_once($CFG->libdir.'/completionlib.php');
@@ -46,6 +46,64 @@ function report_completion_extend_navigation_course($navigation, $course, $conte
}
}
+/**
+ * This function extends the course navigation with the report items
+ *
+ * @param navigation_node $navigation The navigation node to extend
+ * @param stdClass $user
+ * @param stdClass $course The course to object for the report
+ */
+function report_completion_extend_navigation_user($navigation, $user, $course) {
+
+ return; //TODO: this plugin was not linked from navigation in 2.0, let's keep it that way for now --skodak
+
+ if (report_completion_can_access_user_report($user, $course)) {
+ $url = new moodle_url('/report/completion/user.php', array('id'=>$user->id, 'course'=>$course->id));
+ $navigation->add(get_string('coursecompletion'), $url);
+ }
+}
+
+/**
+ * Is current user allowed to access this report
+ *
+ * @private defined in lib.php for performance reasons
+ *
+ * @param stdClass $user
+ * @param stdClass $course
+ * @return bool
+ */
+function report_completion_can_access_user_report($user, $course) {
+ global $USER, $CFG;
+
+ if (empty($CFG->enablecompletion)) {
+ return false;
+ }
+
+ if ($course->id != SITEID and !$course->enablecompletion) {
+ return;
+ }
+
+ $coursecontext = context_course::instance($course->id);
+ $personalcontext = context_user::instance($user->id);
+
+ if (has_capability('report/completion:view', $coursecontext)) {
+ return true;
+ }
+
+ if (has_capability('moodle/user:viewuseractivitiesreport', $personalcontext)) {
+ if ($course->showreports and (is_viewing($coursecontext, $user) or is_enrolled($coursecontext, $user))) {
+ return true;
+ }
+
+ } else if ($user->id == $USER->id) {
+ if ($course->showreports and (is_viewing($coursecontext, $USER) or is_enrolled($coursecontext, $USER))) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
/**
* Return a list of page types
* @param string $pagetype current page type
diff --git a/report/completion/user.php b/report/completion/user.php
new file mode 100644
index 00000000000..0a7988d7b7d
--- /dev/null
+++ b/report/completion/user.php
@@ -0,0 +1,303 @@
+.
+
+/**
+ * Display user completion report
+ *
+ * @package report
+ * @subpackage completion
+ * @copyright 2009 Catalyst IT Ltd
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require('../../config.php');
+require_once($CFG->dirroot.'/report/completion/lib.php');
+require_once($CFG->libdir.'/completionlib.php');
+
+$userid = required_param('id', PARAM_INT);
+$courseid = required_param('course', PARAM_INT);
+
+$user = $DB->get_record('user', array('id'=>$userid, 'deleted'=>0), '*', MUST_EXIST);
+$course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST);
+
+$coursecontext = context_course::instance($course->id);
+$personalcontext = context_user::instance($user->id);
+
+if ($USER->id != $user->id and has_capability('moodle/user:viewuseractivitiesreport', $personalcontext)
+ and !is_enrolled($coursecontext, $USER) and is_enrolled($coursecontext, $user)) {
+ //TODO: do not require parents to be enrolled in courses - this is a hack!
+ require_login();
+ $PAGE->set_course($course);
+} else {
+ require_login($course);
+}
+
+if (!report_completion_can_access_user_report($user, $course, true)) {
+ // this should never happen
+ error('Can not access user completion report');
+}
+
+add_to_log($course->id, 'course', 'report completion', "report/completion/user.php?id=$user->id&course=$course->id", $course->id);
+
+$stractivityreport = get_string('activityreport');
+
+$PAGE->set_pagelayout('admin');
+$PAGE->set_url('/report/completion/user.php', array('id'=>$user->id, 'course'=>$course->id));
+$PAGE->navigation->extend_for_user($user);
+$PAGE->navigation->set_userid_for_parent_checks($user->id); // see MDL-25805 for reasons and for full commit reference for reversal when fixed.
+$PAGE->set_title("$course->shortname: $stractivityreport");
+$PAGE->set_heading($course->fullname);
+echo $OUTPUT->header();
+
+
+// Display course completion user report
+
+// Grab all courses the user is enrolled in and their completion status
+$sql = "
+ SELECT DISTINCT
+ c.id AS id
+ FROM
+ {course} c
+ INNER JOIN
+ {context} con
+ ON con.instanceid = c.id
+ INNER JOIN
+ {role_assignments} ra
+ ON ra.contextid = con.id
+ INNER JOIN
+ {enrol} e
+ ON c.id = e.courseid
+ INNER JOIN
+ {user_enrolments} ue
+ ON e.id = ue.enrolid AND ra.userid = ue.userid
+ AND ra.userid = {$user->id}
+";
+
+// Get roles that are tracked by course completion
+if ($roles = $CFG->gradebookroles) {
+ $sql .= '
+ AND ra.roleid IN ('.$roles.')
+ ';
+}
+
+$sql .= '
+ WHERE
+ con.contextlevel = '.CONTEXT_COURSE.'
+ AND c.enablecompletion = 1
+';
+
+
+// If we are looking at a specific course
+if ($course->id != 1) {
+ $sql .= '
+ AND c.id = '.(int)$course->id.'
+ ';
+}
+
+// Check if result is empty
+$rs = $DB->get_recordset_sql($sql);
+if (!$rs->valid()) {
+
+ if ($course->id != 1) {
+ $error = get_string('nocompletions', 'report_completion'); // TODO: missing string
+ } else {
+ $error = get_string('nocompletioncoursesenroled', 'report_completion'); // TODO: missing string
+ }
+
+ echo $OUTPUT->notification($error);
+ $rs->close(); // not going to loop (but break), close rs
+ echo $OUTPUT->footer();
+ die();
+}
+
+// Categorize courses by their status
+$courses = array(
+ 'inprogress' => array(),
+ 'complete' => array(),
+ 'unstarted' => array()
+);
+
+// Sort courses by the user's status in each
+foreach ($rs as $course_completion) {
+ $c_info = new completion_info((object)$course_completion);
+
+ // Is course complete?
+ $coursecomplete = $c_info->is_course_complete($user->id);
+
+ // Has this user completed any criteria?
+ $criteriacomplete = $c_info->count_course_user_data($user->id);
+
+ if ($coursecomplete) {
+ $courses['complete'][] = $c_info;
+ } else if ($criteriacomplete) {
+ $courses['inprogress'][] = $c_info;
+ } else {
+ $courses['unstarted'][] = $c_info;
+ }
+}
+$rs->close(); // after loop, close rs
+
+// Loop through course status groups
+foreach ($courses as $type => $infos) {
+
+ // If there are courses with this status
+ if (!empty($infos)) {
+
+ echo ''.get_string($type, 'report_completion').'
';
+ echo '';
+ echo '';
+
+ // For each course
+ foreach ($infos as $c_info) {
+
+ // Get course info
+ $c_course = $DB->get_record('course', array('id' => $c_info->course_id));
+ $course_context = get_context_instance(CONTEXT_COURSE, $c_course->id, MUST_EXIST);
+ $course_name = format_string($c_course->fullname, true, array('context' => $course_context));
+
+ // Get completions
+ $completions = $c_info->get_completions($user->id);
+
+ // Save row data
+ $rows = array();
+
+ // For aggregating activity completion
+ $activities = array();
+ $activities_complete = 0;
+
+ // For aggregating prerequisites
+ $prerequisites = array();
+ $prerequisites_complete = 0;
+
+ // Loop through course criteria
+ foreach ($completions as $completion) {
+ $criteria = $completion->get_criteria();
+ $complete = $completion->is_complete();
+
+ // Activities are a special case, so cache them and leave them till last
+ if ($criteria->criteriatype == COMPLETION_CRITERIA_TYPE_ACTIVITY) {
+ $activities[$criteria->moduleinstance] = $complete;
+
+ if ($complete) {
+ $activities_complete++;
+ }
+
+ continue;
+ }
+
+ // Prerequisites are also a special case, so cache them and leave them till last
+ if ($criteria->criteriatype == COMPLETION_CRITERIA_TYPE_COURSE) {
+ $prerequisites[$criteria->courseinstance] = $complete;
+
+ if ($complete) {
+ $prerequisites_complete++;
+ }
+
+ continue;
+ }
+
+ $row = array();
+ $row['title'] = $criteria->get_title();
+ $row['status'] = $completion->get_status();
+ $rows[] = $row;
+ }
+
+ // Aggregate activities
+ if (!empty($activities)) {
+
+ $row = array();
+ $row['title'] = get_string('activitiescomplete', 'report_completion');
+ $row['status'] = $activities_complete.' of '.count($activities);
+ $rows[] = $row;
+ }
+
+ // Aggregate prerequisites
+ if (!empty($prerequisites)) {
+
+ $row = array();
+ $row['title'] = get_string('prerequisitescompleted', 'completion');
+ $row['status'] = $prerequisites_complete.' of '.count($prerequisites);
+ array_splice($rows, 0, 0, array($row));
+ }
+
+ $first_row = true;
+
+ // Print table
+ foreach ($rows as $row) {
+
+ // Display course name on first row
+ if ($first_row) {
+ echo '| '.$course_name.' | ';
+ } else {
+ echo '
| ';
+ }
+
+ echo '';
+ echo $row['title'];
+ echo ' | ';
+
+ switch ($row['status']) {
+ case 'Yes':
+ echo get_string('complete');
+ break;
+
+ case 'No':
+ echo get_string('incomplete', 'report_completion');
+ break;
+
+ default:
+ echo $row['status'];
+ }
+
+ // Display link on first row
+ echo ' | ';
+ if ($first_row) {
+ echo ''.get_string('detailedview', 'report_completion').'';
+ }
+ echo ' | ';
+
+ // Display completion date for completed courses on first row
+ if ($type === 'complete' && $first_row) {
+ $params = array(
+ 'userid' => $user->id,
+ 'course' => $c_course->id
+ );
+
+ $ccompletion = new completion_completion($params);
+ echo ''.userdate($ccompletion->timecompleted, '%e %B %G').' | ';
+ }
+
+ $first_row = false;
+ echo '
';
+ }
+ }
+
+ echo '
';
+ }
+}
+
+
+echo $OUTPUT->footer();