$current_group = false; $col_count = 0; for ($i = 0; $i <= count($criteria); $i++) { if (isset($criteria[$i])) { $criterion = $criteria[$i]; if ($current_group && $criterion->criteriatype === $current_group->criteriatype) { ++$col_count; continue; } } // Print header cell if ($col_count) { $has_agg = array(COMPLETION_CRITERIA_TYPE_COURSE, COMPLETION_CRITERIA_TYPE_ACTIVITY, COMPLETION_CRITERIA_TYPE_ROLE); if (in_array($current_group->criteriatype, $has_agg)) { // Try load a aggregation method $method = $completion->get_aggregation_method($current_group->criteriatype); $method = $method == 1 ? get_string('all') : get_string('any'); } else { $method = '-'; } print '<th scope="col" colspan="' . $col_count . '" class="colheader aggheader">' . $method . '</th>'; } if (isset($criteria[$i])) { // Move to next criteria type $current_group = $criterion; $col_count = 1; } } // Overall course aggregation method print '<th scope="col" class="colheader aggheader aggcriteriacourse">'; // Get course aggregation
public function get_content() { global $USER, $CFG, $DB, $COURSE; // If content is cached if ($this->content !== NULL) { return $this->content; } // Create empty content $this->content = new stdClass(); // Can edit settings? $can_edit = has_capability('moodle/course:update', get_context_instance(CONTEXT_COURSE, $this->page->course->id)); // Get course completion data $info = new completion_info($this->page->course); // Don't display if completion isn't enabled! if (!completion_info::is_enabled_for_site()) { if ($can_edit) { $this->content->text = get_string('completionnotenabledforsite', 'completion'); } return $this->content; } else { if (!$info->is_enabled()) { if ($can_edit) { $this->content->text = get_string('completionnotenabledforcourse', 'completion'); } return $this->content; } } // Load criteria to display $completions = $info->get_completions($USER->id); // Check if this course has any criteria if (empty($completions)) { if ($can_edit) { $this->content->text = get_string('nocriteriaset', 'completion'); } return $this->content; } // Check this user is enroled if (!$info->is_tracked_user($USER->id)) { // If not enrolled, but are can view the report: if (has_capability('report/completion:view', get_context_instance(CONTEXT_COURSE, $COURSE->id))) { $this->content->text = '<a href="' . $CFG->wwwroot . '/report/completion/index.php?course=' . $COURSE->id . '">' . get_string('viewcoursereport', 'completion') . '</a>'; return $this->content; } // Otherwise, show error $this->content->text = get_string('notenroled', 'completion'); return $this->content; } // Generate markup for criteria statuses $shtml = ''; // For aggregating activity completion $activities = array(); $activities_complete = 0; // For aggregating course prerequisites $prerequisites = array(); $prerequisites_complete = 0; // Flag to set if current completion data is inconsistent with // what is stored in the database $pending_update = false; // Loop through course criteria foreach ($completions as $completion) { $criteria = $completion->get_criteria(); $complete = $completion->is_complete(); if (!$pending_update && $criteria->is_pending($completion)) { $pending_update = true; } // 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; } $shtml .= '<tr><td>'; $shtml .= $criteria->get_title(); $shtml .= '</td><td style="text-align: right">'; $shtml .= $completion->get_status(); $shtml .= '</td></tr>'; } // Aggregate activities if (!empty($activities)) { $shtml .= '<tr><td>'; $shtml .= get_string('activitiescompleted', 'completion'); $shtml .= '</td><td style="text-align: right">'; $a = new stdClass(); $a->first = $activities_complete; $a->second = count($activities); $shtml .= get_string('firstofsecond', 'block_completionstatus', $a); $shtml .= '</td></tr>'; } // Aggregate prerequisites if (!empty($prerequisites)) { $phtml = '<tr><td>'; $phtml .= get_string('prerequisitescompleted', 'completion'); $phtml .= '</td><td style="text-align: right">'; $a = new stdClass(); $a->first = $prerequisites_complete; $a->second = count($prerequisites); $shtml .= get_string('firstofsecond', 'block_completionstatus', $a); $phtml .= '</td></tr>'; $shtml = $phtml . $shtml; } // Display completion status $this->content->text = '<table width="100%" style="font-size: 90%;"><tbody>'; $this->content->text .= '<tr><td colspan="2"><b>' . get_string('status') . ':</b> '; // Is course complete? $coursecomplete = $info->is_course_complete($USER->id); // Load course completion $params = array('userid' => $USER->id, 'course' => $COURSE->id); $ccompletion = new completion_completion($params); // Has this user completed any criteria? $criteriacomplete = $info->count_course_user_data($USER->id); if ($pending_update) { $this->content->text .= '<i>' . get_string('pending', 'completion') . '</i>'; } else { if ($coursecomplete) { $this->content->text .= get_string('complete'); } else { if (!$criteriacomplete && !$ccompletion->timestarted) { $this->content->text .= '<i>' . get_string('notyetstarted', 'completion') . '</i>'; } else { $this->content->text .= '<i>' . get_string('inprogress', 'completion') . '</i>'; } } } $this->content->text .= '</td></tr>'; $this->content->text .= '<tr><td colspan="2">'; // Get overall aggregation method $overall = $info->get_aggregation_method(); if ($overall == COMPLETION_AGGREGATION_ALL) { $this->content->text .= get_string('criteriarequiredall', 'completion'); } else { $this->content->text .= get_string('criteriarequiredany', 'completion'); } $this->content->text .= ':</td></tr>'; $this->content->text .= '<tr><td><b>' . get_string('requiredcriteria', 'completion') . '</b></td><td style="text-align: right"><b>' . get_string('status') . '</b></td></tr>'; $this->content->text .= $shtml . '</tbody></table>'; // Display link to detailed view $this->content->footer = '<br><a href="' . $CFG->wwwroot . '/blocks/completionstatus/details.php?course=' . $COURSE->id . '">' . get_string('moredetails', 'completion') . '</a>'; return $this->content; }
// Check if this course has any criteria. if (empty($completions)) { echo html_writer::start_tag('tr'); echo html_writer::start_tag('td', array('colspan' => '2')); echo html_writer::start_tag('br'); echo $OUTPUT->box(get_string('err_nocriteria', 'completion'), 'noticebox'); echo html_writer::end_tag('td'); echo html_writer::end_tag('tr'); echo html_writer::end_tag('tbody'); echo html_writer::end_tag('table'); } else { echo html_writer::start_tag('tr'); echo html_writer::start_tag('td', array('colspan' => '2')); echo html_writer::tag('b', get_string('required')); // Get overall aggregation method. $overall = $info->get_aggregation_method(); if ($overall == COMPLETION_AGGREGATION_ALL) { echo get_string('criteriarequiredall', 'completion'); } else { echo get_string('criteriarequiredany', 'completion'); } echo html_writer::end_tag('td'); echo html_writer::end_tag('tr'); echo html_writer::end_tag('tbody'); echo html_writer::end_tag('table'); // Generate markup for criteria statuses. echo html_writer::start_tag('table', array('class' => 'generalbox logtable boxaligncenter', 'id' => 'criteriastatus', 'width' => '100%')); echo html_writer::start_tag('tbody'); echo html_writer::start_tag('tr', array('class' => 'ccheader')); echo html_writer::tag('th', get_string('criteriagroup', 'block_completionstatus'), array('class' => 'c0 header', 'scope' => 'col')); echo html_writer::tag('th', get_string('criteria', 'completion'), array('class' => 'c1 header', 'scope' => 'col'));
/** * Aggregate each user's criteria completions * * @return void */ function completion_cron_completions() { global $DB; if (debugging()) { mtrace('Aggregating completions'); } // Save time started $timestarted = time(); // Grab all criteria and their associated criteria completions $sql = ' SELECT DISTINCT c.id AS course, cr.id AS criteriaid, crc.userid AS userid, cr.criteriatype AS criteriatype, cc.timecompleted AS timecompleted FROM {course_completion_criteria} cr INNER JOIN {course} c ON cr.course = c.id INNER JOIN {course_completions} crc ON crc.course = c.id LEFT JOIN {course_completion_crit_compl} cc ON cc.criteriaid = cr.id AND crc.userid = cc.userid WHERE c.enablecompletion = 1 AND crc.timecompleted IS NULL AND crc.reaggregate > 0 AND crc.reaggregate < :timestarted ORDER BY course, userid '; // Check if result is empty if (!($rs = $DB->get_recordset_sql($sql, array('timestarted' => $timestarted)))) { return; } $current_user = null; $current_course = null; $completions = array(); while (1) { // Grab records for current user/course foreach ($rs as $record) { // If we are still grabbing the same users completions if ($record->userid === $current_user && $record->course === $current_course) { $completions[$record->criteriaid] = $record; } else { break; } } // Aggregate if (!empty($completions)) { if (debugging()) { mtrace('Aggregating completions for user ' . $current_user . ' in course ' . $current_course); } // Get course info object $info = new completion_info((object) array('id' => $current_course)); // Setup aggregation $overall = $info->get_aggregation_method(); $activity = $info->get_aggregation_method(COMPLETION_CRITERIA_TYPE_ACTIVITY); $prerequisite = $info->get_aggregation_method(COMPLETION_CRITERIA_TYPE_COURSE); $role = $info->get_aggregation_method(COMPLETION_CRITERIA_TYPE_ROLE); $overall_status = null; $activity_status = null; $prerequisite_status = null; $role_status = null; // Get latest timecompleted $timecompleted = null; // Check each of the criteria foreach ($completions as $params) { $timecompleted = max($timecompleted, $params->timecompleted); $completion = new completion_criteria_completion($params, false); // Handle aggregation special cases if ($params->criteriatype == COMPLETION_CRITERIA_TYPE_ACTIVITY) { completion_cron_aggregate($activity, $completion->is_complete(), $activity_status); } else { if ($params->criteriatype == COMPLETION_CRITERIA_TYPE_COURSE) { completion_cron_aggregate($prerequisite, $completion->is_complete(), $prerequisite_status); } else { if ($params->criteriatype == COMPLETION_CRITERIA_TYPE_ROLE) { completion_cron_aggregate($role, $completion->is_complete(), $role_status); } else { completion_cron_aggregate($overall, $completion->is_complete(), $overall_status); } } } } // Include role criteria aggregation in overall aggregation if ($role_status !== null) { completion_cron_aggregate($overall, $role_status, $overall_status); } // Include activity criteria aggregation in overall aggregation if ($activity_status !== null) { completion_cron_aggregate($overall, $activity_status, $overall_status); } // Include prerequisite criteria aggregation in overall aggregation if ($prerequisite_status !== null) { completion_cron_aggregate($overall, $prerequisite_status, $overall_status); } // If aggregation status is true, mark course complete for user if ($overall_status) { if (debugging()) { mtrace('Marking complete'); } $ccompletion = new completion_completion(array('course' => $params->course, 'userid' => $params->userid)); $ccompletion->mark_complete($timecompleted); } } // If this is the end of the recordset, break the loop if (!$rs->valid()) { $rs->close(); break; } // New/next user, update user details, reset completions $current_user = $record->userid; $current_course = $record->course; $completions = array(); $completions[$record->criteriaid] = $record; } // Mark all users as aggregated $sql = "\n UPDATE\n {course_completions}\n SET\n reaggregate = 0\n WHERE\n reaggregate < {$timestarted}\n "; $DB->execute($sql); }
/** * Get Course completion status * * @param int $courseid ID of the Course * @param int $userid ID of the User * @return array of course completion status and warnings * @since Moodle 2.9 * @throws moodle_exception */ public static function get_course_completion_status($courseid, $userid) { global $CFG, $USER; require_once $CFG->libdir . '/grouplib.php'; $warnings = array(); $arrayparams = array('courseid' => $courseid, 'userid' => $userid); $params = self::validate_parameters(self::get_course_completion_status_parameters(), $arrayparams); $course = get_course($params['courseid']); $user = core_user::get_user($params['userid'], 'id', MUST_EXIST); $context = context_course::instance($course->id); self::validate_context($context); // Can current user see user's course completion status? // This check verifies if completion is enabled because $course is mandatory. if (!completion_can_view_data($user->id, $course)) { throw new moodle_exception('cannotviewreport'); } // The previous function doesn't check groups. if ($user->id != $USER->id) { if (!groups_user_groups_visible($course, $user->id)) { // We are not in the same group! throw new moodle_exception('accessdenied', 'admin'); } } $info = new completion_info($course); // Check this user is enroled. if (!$info->is_tracked_user($user->id)) { if ($USER->id == $user->id) { throw new moodle_exception('notenroled', 'completion'); } else { throw new moodle_exception('usernotenroled', 'completion'); } } $completions = $info->get_completions($user->id); if (empty($completions)) { throw new moodle_exception('nocriteriaset', 'completion'); } // Load course completion. $completionparams = array('userid' => $user->id, 'course' => $course->id); $ccompletion = new completion_completion($completionparams); $completionrows = array(); // Loop through course criteria. foreach ($completions as $completion) { $criteria = $completion->get_criteria(); $completionrow = array(); $completionrow['type'] = $criteria->criteriatype; $completionrow['title'] = $criteria->get_title(); $completionrow['status'] = $completion->get_status(); $completionrow['complete'] = $completion->is_complete(); $completionrow['timecompleted'] = $completion->timecompleted; $completionrow['details'] = $criteria->get_details($completion); $completionrows[] = $completionrow; } $result = array('completed' => $info->is_course_complete($user->id), 'aggregation' => $info->get_aggregation_method(), 'completions' => $completionrows); $results = array('completionstatus' => $result, 'warnings' => $warnings); return $results; }
function definition() { global $USER, $CFG, $DB, $js_enabled; $courseconfig = get_config('moodlecourse'); $mform =& $this->_form; $course = $this->_customdata['course']; $completion = new completion_info($course); $params = array('course' => $course->id); /// form definition //-------------------------------------------------------------------------------- // Check if there is existing criteria completions if ($completion->is_course_locked()) { $mform->addElement('header', '', get_string('completionsettingslocked', 'completion')); $mform->addElement('static', '', '', get_string('err_settingslocked', 'completion')); $mform->addElement('submit', 'settingsunlock', get_string('unlockcompletiondelete', 'completion')); } // Get array of all available aggregation methods $aggregation_methods = $completion->get_aggregation_methods(); // Overall criteria aggregation $mform->addElement('header', 'overallcriteria', get_string('overallcriteriaaggregation', 'completion')); $mform->addElement('select', 'overall_aggregation', get_string('aggregationmethod', 'completion'), $aggregation_methods); $mform->setDefault('overall_aggregation', $completion->get_aggregation_method()); // Course prerequisite completion criteria $mform->addElement('header', 'courseprerequisites', get_string('courseprerequisites', 'completion')); // Get applicable courses $courses = $DB->get_records_sql("\n SELECT DISTINCT\n c.id,\n c.category,\n c.fullname,\n cc.id AS selected\n FROM\n {course} c\n LEFT JOIN\n {course_completion_criteria} cc\n ON cc.courseinstance = c.id\n AND cc.course = {$course->id}\n INNER JOIN\n {course_completion_criteria} ccc\n ON ccc.course = c.id\n WHERE\n c.enablecompletion = " . COMPLETION_ENABLED . "\n AND c.id <> {$course->id}\n "); if (!empty($courses)) { if (count($courses) > 1) { $mform->addElement('select', 'course_aggregation', get_string('aggregationmethod', 'completion'), $aggregation_methods); $mform->setDefault('course_aggregation', $completion->get_aggregation_method(COMPLETION_CRITERIA_TYPE_COURSE)); } // Get category list $list = array(); $parents = array(); make_categories_list($list, $parents); // Get course list for select box $selectbox = array(); $selected = array(); foreach ($courses as $c) { $selectbox[$c->id] = $list[$c->category] . ' / ' . s($c->fullname); // If already selected if ($c->selected) { $selected[] = $c->id; } } // Show multiselect box $mform->addElement('select', 'criteria_course', get_string('coursesavailable', 'completion'), $selectbox, array('multiple' => 'multiple', 'size' => 6)); // Select current criteria $mform->setDefault('criteria_course', $selected); // Explain list $mform->addElement('static', 'criteria_courses_explaination', '', get_string('coursesavailableexplaination', 'completion')); } else { $mform->addElement('static', 'nocourses', '', get_string('err_nocourses', 'completion')); } // Manual self completion $mform->addElement('header', 'manualselfcompletion', get_string('manualselfcompletion', 'completion')); $criteria = new completion_criteria_self($params); $criteria->config_form_display($mform); // Role completion criteria $mform->addElement('header', 'roles', get_string('manualcompletionby', 'completion')); $roles = get_roles_with_capability('moodle/course:markcomplete', CAP_ALLOW, get_context_instance(CONTEXT_COURSE, $course->id)); if (!empty($roles)) { $mform->addElement('select', 'role_aggregation', get_string('aggregationmethod', 'completion'), $aggregation_methods); $mform->setDefault('role_aggregation', $completion->get_aggregation_method(COMPLETION_CRITERIA_TYPE_ROLE)); foreach ($roles as $role) { $params_a = array('role' => $role->id); $criteria = new completion_criteria_role(array_merge($params, $params_a)); $criteria->config_form_display($mform, $role); } } else { $mform->addElement('static', 'noroles', '', get_string('err_noroles', 'completion')); } // Activity completion criteria $mform->addElement('header', 'activitiescompleted', get_string('activitiescompleted', 'completion')); $activities = $completion->get_activities(); if (!empty($activities)) { if (count($activities) > 1) { $mform->addElement('select', 'activity_aggregation', get_string('aggregationmethod', 'completion'), $aggregation_methods); $mform->setDefault('activity_aggregation', $completion->get_aggregation_method(COMPLETION_CRITERIA_TYPE_ACTIVITY)); } foreach ($activities as $activity) { $params_a = array('moduleinstance' => $activity->id); $criteria = new completion_criteria_activity(array_merge($params, $params_a)); $criteria->config_form_display($mform, $activity); } } else { $mform->addElement('static', 'noactivities', '', get_string('err_noactivities', 'completion')); } // Completion on date $mform->addElement('header', 'date', get_string('date')); $criteria = new completion_criteria_date($params); $criteria->config_form_display($mform); // Completion after enrolment duration $mform->addElement('header', 'duration', get_string('durationafterenrolment', 'completion')); $criteria = new completion_criteria_duration($params); $criteria->config_form_display($mform); // Completion on course grade $mform->addElement('header', 'grade', get_string('grade')); // Grade enable and passing grade $course_grade = $DB->get_field('grade_items', 'gradepass', array('courseid' => $course->id, 'itemtype' => 'course')); $criteria = new completion_criteria_grade($params); $criteria->config_form_display($mform, $course_grade); // Completion on unenrolment $mform->addElement('header', 'unenrolment', get_string('unenrolment', 'completion')); $criteria = new completion_criteria_unenrol($params); $criteria->config_form_display($mform); //-------------------------------------------------------------------------------- $this->add_action_buttons(); //-------------------------------------------------------------------------------- $mform->addElement('hidden', 'id', $course->id); $mform->setType('id', PARAM_INT); // If the criteria are locked, freeze values and submit button if ($completion->is_course_locked()) { $except = array('settingsunlock'); $mform->hardFreezeAllVisibleExcept($except); $mform->addElement('cancel'); } }
public function get_content() { global $USER; $rows = array(); $srows = array(); $prows = array(); // If content is cached. if ($this->content !== null) { return $this->content; } $course = $this->page->course; $context = context_course::instance($course->id); // Create empty content. $this->content = new stdClass(); $this->content->text = ''; $this->content->footer = ''; // Can edit settings? $can_edit = has_capability('moodle/course:update', $context); // Get course completion data. $info = new completion_info($course); // Don't display if completion isn't enabled! if (!completion_info::is_enabled_for_site()) { if ($can_edit) { $this->content->text .= get_string('completionnotenabledforsite', 'completion'); } return $this->content; } else { if (!$info->is_enabled()) { if ($can_edit) { $this->content->text .= get_string('completionnotenabledforcourse', 'completion'); } return $this->content; } } // Load criteria to display. $completions = $info->get_completions($USER->id); // Check if this course has any criteria. if (empty($completions)) { if ($can_edit) { $this->content->text .= get_string('nocriteriaset', 'completion'); } return $this->content; } // Check this user is enroled. if ($info->is_tracked_user($USER->id)) { // Generate markup for criteria statuses. $data = ''; // For aggregating activity completion. $activities = array(); $activities_complete = 0; // For aggregating course prerequisites. $prerequisites = array(); $prerequisites_complete = 0; // Flag to set if current completion data is inconsistent with what is stored in the database. $pending_update = false; // Loop through course criteria. foreach ($completions as $completion) { $criteria = $completion->get_criteria(); $complete = $completion->is_complete(); if (!$pending_update && $criteria->is_pending($completion)) { $pending_update = true; } // 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 = new html_table_row(); $row->cells[0] = new html_table_cell($criteria->get_title()); $row->cells[1] = new html_table_cell($completion->get_status()); $row->cells[1]->style = 'text-align: right;'; $srows[] = $row; } // Aggregate activities. if (!empty($activities)) { $a = new stdClass(); $a->first = $activities_complete; $a->second = count($activities); $row = new html_table_row(); $row->cells[0] = new html_table_cell(get_string('activitiescompleted', 'completion')); $row->cells[1] = new html_table_cell(get_string('firstofsecond', 'block_completionstatus', $a)); $row->cells[1]->style = 'text-align: right;'; $srows[] = $row; } // Aggregate prerequisites. if (!empty($prerequisites)) { $a = new stdClass(); $a->first = $prerequisites_complete; $a->second = count($prerequisites); $row = new html_table_row(); $row->cells[0] = new html_table_cell(get_string('dependenciescompleted', 'completion')); $row->cells[1] = new html_table_cell(get_string('firstofsecond', 'block_completionstatus', $a)); $row->cells[1]->style = 'text-align: right;'; $prows[] = $row; $srows = array_merge($prows, $srows); } // Display completion status. $table = new html_table(); $table->width = '100%'; $table->attributes = array('style' => 'font-size: 90%;', 'class' => ''); $row = new html_table_row(); $content = html_writer::tag('b', get_string('status') . ': '); // Is course complete? $coursecomplete = $info->is_course_complete($USER->id); // Load course completion. $params = array('userid' => $USER->id, 'course' => $course->id); $ccompletion = new completion_completion($params); // Has this user completed any criteria? $criteriacomplete = $info->count_course_user_data($USER->id); if ($pending_update) { $content .= html_writer::tag('i', get_string('pending', 'completion')); } else { if ($coursecomplete) { $content .= get_string('complete'); } else { if (!$criteriacomplete && !$ccompletion->timestarted) { $content .= html_writer::tag('i', get_string('notyetstarted', 'completion')); } else { $content .= html_writer::tag('i', get_string('inprogress', 'completion')); } } } $row->cells[0] = new html_table_cell($content); $row->cells[0]->colspan = '2'; $rows[] = $row; $row = new html_table_row(); $content = ""; // Get overall aggregation method. $overall = $info->get_aggregation_method(); if ($overall == COMPLETION_AGGREGATION_ALL) { $content .= get_string('criteriarequiredall', 'completion'); } else { $content .= get_string('criteriarequiredany', 'completion'); } $content .= ':'; $row->cells[0] = new html_table_cell($content); $row->cells[0]->colspan = '2'; $rows[] = $row; $row = new html_table_row(); $row->cells[0] = new html_table_cell(html_writer::tag('b', get_string('requiredcriteria', 'completion'))); $row->cells[1] = new html_table_cell(html_writer::tag('b', get_string('status'))); $row->cells[1]->style = 'text-align: right;'; $rows[] = $row; // Array merge $rows and $data here. $rows = array_merge($rows, $srows); $table->data = $rows; $this->content->text .= html_writer::table($table); // Display link to detailed view. $details = new moodle_url('/blocks/completionstatus/details.php', array('course' => $course->id)); $this->content->footer .= html_writer::link($details, get_string('moredetails', 'completion')); } else { // If user is not enrolled, show error. $this->content->text = get_string('nottracked', 'completion'); } if (has_capability('report/completion:view', $context)) { $report = new moodle_url('/report/completion/index.php', array('course' => $course->id)); if (empty($this->content->footer)) { $this->content->footer = ''; } $this->content->footer .= html_writer::empty_tag('br'); $this->content->footer .= html_writer::link($report, get_string('viewcoursereport', 'completion')); } return $this->content; }
/** * Defines the form fields. */ public function definition() { global $USER, $CFG, $DB; $courseconfig = get_config('moodlecourse'); $mform = $this->_form; $course = $this->_customdata['course']; $completion = new completion_info($course); $params = array('course' => $course->id); // Check if there are existing criteria completions. if ($completion->is_course_locked()) { $mform->addElement('header', 'completionsettingslocked', get_string('completionsettingslocked', 'completion')); $mform->addElement('static', '', '', get_string('err_settingslocked', 'completion')); $mform->addElement('submit', 'settingsunlock', get_string('unlockcompletiondelete', 'completion')); } // Get array of all available aggregation methods. $aggregation_methods = $completion->get_aggregation_methods(); // Overall criteria aggregation. $mform->addElement('header', 'overallcriteria', get_string('general', 'core_form')); // Map aggregation methods to context-sensitive human readable dropdown menu. $overallaggregationmenu = array(); foreach ($aggregation_methods as $methodcode => $methodname) { if ($methodcode === COMPLETION_AGGREGATION_ALL) { $overallaggregationmenu[COMPLETION_AGGREGATION_ALL] = get_string('overallaggregation_all', 'core_completion'); } else { if ($methodcode === COMPLETION_AGGREGATION_ANY) { $overallaggregationmenu[COMPLETION_AGGREGATION_ANY] = get_string('overallaggregation_any', 'core_completion'); } else { $overallaggregationmenu[$methodcode] = $methodname; } } } $mform->addElement('select', 'overall_aggregation', get_string('overallaggregation', 'core_completion'), $overallaggregationmenu); $mform->setDefault('overall_aggregation', $completion->get_aggregation_method()); // Activity completion criteria $label = get_string('coursecompletioncondition', 'core_completion', get_string('activitiescompleted', 'core_completion')); $mform->addElement('header', 'activitiescompleted', $label); // Get the list of currently specified conditions and expand the section if some are found. $current = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_ACTIVITY); if (!empty($current)) { $mform->setExpanded('activitiescompleted'); } $activities = $completion->get_activities(); if (!empty($activities)) { if (!$completion->is_course_locked()) { $this->add_checkbox_controller(1, null, null, 0); } foreach ($activities as $activity) { $params_a = array('moduleinstance' => $activity->id); $criteria = new completion_criteria_activity(array_merge($params, $params_a)); $criteria->config_form_display($mform, $activity); } $mform->addElement('static', 'criteria_role_note', '', get_string('activitiescompletednote', 'core_completion')); if (count($activities) > 1) { // Map aggregation methods to context-sensitive human readable dropdown menu. $activityaggregationmenu = array(); foreach ($aggregation_methods as $methodcode => $methodname) { if ($methodcode === COMPLETION_AGGREGATION_ALL) { $activityaggregationmenu[COMPLETION_AGGREGATION_ALL] = get_string('activityaggregation_all', 'core_completion'); } else { if ($methodcode === COMPLETION_AGGREGATION_ANY) { $activityaggregationmenu[COMPLETION_AGGREGATION_ANY] = get_string('activityaggregation_any', 'core_completion'); } else { $activityaggregationmenu[$methodcode] = $methodname; } } } $mform->addElement('select', 'activity_aggregation', get_string('activityaggregation', 'core_completion'), $activityaggregationmenu); $mform->setDefault('activity_aggregation', $completion->get_aggregation_method(COMPLETION_CRITERIA_TYPE_ACTIVITY)); } } else { $mform->addElement('static', 'noactivities', '', get_string('err_noactivities', 'completion')); } // Course prerequisite completion criteria. $label = get_string('coursecompletioncondition', 'core_completion', get_string('dependenciescompleted', 'core_completion')); $mform->addElement('header', 'courseprerequisites', $label); // Get the list of currently specified conditions and expand the section if some are found. $current = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_COURSE); if (!empty($current)) { $mform->setExpanded('courseprerequisites'); } // Get applicable courses (prerequisites). $courses = $DB->get_records_sql("\n SELECT DISTINCT c.id, c.category, c.fullname, cc.id AS selected\n FROM {course} c\n LEFT JOIN {course_completion_criteria} cc ON cc.courseinstance = c.id AND cc.course = {$course->id}\n INNER JOIN {course_completion_criteria} ccc ON ccc.course = c.id\n WHERE c.enablecompletion = " . COMPLETION_ENABLED . "\n AND c.id <> {$course->id}"); if (!empty($courses)) { // Get category list. require_once $CFG->libdir . '/coursecatlib.php'; $list = coursecat::make_categories_list(); // Get course list for select box. $selectbox = array(); $selected = array(); foreach ($courses as $c) { $selectbox[$c->id] = $list[$c->category] . ' / ' . format_string($c->fullname, true, array('context' => context_course::instance($c->id))); // If already selected ... if ($c->selected) { $selected[] = $c->id; } } // Show multiselect box. $mform->addElement('select', 'criteria_course', get_string('coursesavailable', 'completion'), $selectbox, array('multiple' => 'multiple', 'size' => 6)); // Select current criteria. $mform->setDefault('criteria_course', $selected); // Explain list. $mform->addElement('static', 'criteria_courses_explaination', '', get_string('coursesavailableexplaination', 'completion')); if (count($courses) > 1) { // Map aggregation methods to context-sensitive human readable dropdown menu. $courseaggregationmenu = array(); foreach ($aggregation_methods as $methodcode => $methodname) { if ($methodcode === COMPLETION_AGGREGATION_ALL) { $courseaggregationmenu[COMPLETION_AGGREGATION_ALL] = get_string('courseaggregation_all', 'core_completion'); } else { if ($methodcode === COMPLETION_AGGREGATION_ANY) { $courseaggregationmenu[COMPLETION_AGGREGATION_ANY] = get_string('courseaggregation_any', 'core_completion'); } else { $courseaggregationmenu[$methodcode] = $methodname; } } } $mform->addElement('select', 'course_aggregation', get_string('courseaggregation', 'core_completion'), $courseaggregationmenu); $mform->setDefault('course_aggregation', $completion->get_aggregation_method(COMPLETION_CRITERIA_TYPE_COURSE)); } } else { $mform->addElement('static', 'nocourses', '', get_string('err_nocourses', 'completion')); } // Completion on date $label = get_string('coursecompletioncondition', 'core_completion', get_string('completionondate', 'core_completion')); $mform->addElement('header', 'date', $label); // Expand the condition section if it is currently enabled. $current = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_DATE); if (!empty($current)) { $mform->setExpanded('date'); } $criteria = new completion_criteria_date($params); $criteria->config_form_display($mform); // Completion after enrolment duration $label = get_string('coursecompletioncondition', 'core_completion', get_string('enrolmentduration', 'core_completion')); $mform->addElement('header', 'duration', $label); // Expand the condition section if it is currently enabled. $current = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_DURATION); if (!empty($current)) { $mform->setExpanded('duration'); } $criteria = new completion_criteria_duration($params); $criteria->config_form_display($mform); // Completion on unenrolment $label = get_string('coursecompletioncondition', 'core_completion', get_string('unenrolment', 'core_completion')); $mform->addElement('header', 'unenrolment', $label); // Expand the condition section if it is currently enabled. $current = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_UNENROL); if (!empty($current)) { $mform->setExpanded('unenrolment'); } $criteria = new completion_criteria_unenrol($params); $criteria->config_form_display($mform); // Completion on course grade $label = get_string('coursecompletioncondition', 'core_completion', get_string('coursegrade', 'core_completion')); $mform->addElement('header', 'grade', $label); // Expand the condition section if it is currently enabled. $current = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_GRADE); if (!empty($current)) { $mform->setExpanded('grade'); } $course_grade = $DB->get_field('grade_items', 'gradepass', array('courseid' => $course->id, 'itemtype' => 'course')); if (!$course_grade) { $course_grade = '0.00000'; } $criteria = new completion_criteria_grade($params); $criteria->config_form_display($mform, $course_grade); // Manual self completion $label = get_string('coursecompletioncondition', 'core_completion', get_string('manualselfcompletion', 'core_completion')); $mform->addElement('header', 'manualselfcompletion', $label); // Expand the condition section if it is currently enabled. $current = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_SELF); if (!empty($current)) { $mform->setExpanded('manualselfcompletion'); } $criteria = new completion_criteria_self($params); $criteria->config_form_display($mform); $mform->addElement('static', 'criteria_self_note', '', get_string('manualselfcompletionnote', 'core_completion')); // Role completion criteria $label = get_string('coursecompletioncondition', 'core_completion', get_string('manualcompletionby', 'core_completion')); $mform->addElement('header', 'roles', $label); // Expand the condition section if it is currently enabled. $current = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_ROLE); if (!empty($current)) { $mform->setExpanded('roles'); } $roles = get_roles_with_capability('moodle/course:markcomplete', CAP_ALLOW, context_course::instance($course->id, IGNORE_MISSING)); if (!empty($roles)) { foreach ($roles as $role) { $params_a = array('role' => $role->id); $criteria = new completion_criteria_role(array_merge($params, $params_a)); $criteria->config_form_display($mform, $role); } $mform->addElement('static', 'criteria_role_note', '', get_string('manualcompletionbynote', 'core_completion')); // Map aggregation methods to context-sensitive human readable dropdown menu. $roleaggregationmenu = array(); foreach ($aggregation_methods as $methodcode => $methodname) { if ($methodcode === COMPLETION_AGGREGATION_ALL) { $roleaggregationmenu[COMPLETION_AGGREGATION_ALL] = get_string('roleaggregation_all', 'core_completion'); } else { if ($methodcode === COMPLETION_AGGREGATION_ANY) { $roleaggregationmenu[COMPLETION_AGGREGATION_ANY] = get_string('roleaggregation_any', 'core_completion'); } else { $roleaggregationmenu[$methodcode] = $methodname; } } } $mform->addElement('select', 'role_aggregation', get_string('roleaggregation', 'core_completion'), $roleaggregationmenu); $mform->setDefault('role_aggregation', $completion->get_aggregation_method(COMPLETION_CRITERIA_TYPE_ROLE)); } else { $mform->addElement('static', 'noroles', '', get_string('err_noroles', 'completion')); } // Add common action buttons. $this->add_action_buttons(); // Add hidden fields. $mform->addElement('hidden', 'id', $course->id); $mform->setType('id', PARAM_INT); // If the criteria are locked, freeze values and submit button. if ($completion->is_course_locked()) { $except = array('settingsunlock'); $mform->hardFreezeAllVisibleExcept($except); $mform->addElement('cancel'); } }