function execute($data, $row, $user, $courseid, $starttime = 0, $endtime = 0) { global $DB, $CFG; require_once("{$CFG->libdir}/completionlib.php"); $course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST); $info = new completion_info($course); // Is course complete? $coursecomplete = $info->is_course_complete($row->id); // Load course completion. $params = array( 'userid' => $row->id, 'course' => $course->id ); $ccompletion = new completion_completion($params); // Has this user completed any criteria? $criteriacomplete = $info->count_course_user_data($row->id); $content = ""; 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')); } return $content; }
public function get_content() { global $CFG, $USER; // 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; } } // Get this user's data $completion = $info->get_completion($USER->id, COMPLETION_CRITERIA_TYPE_SELF); // Check if self completion is one of this course's criteria if (empty($completion)) { if ($can_edit) { $this->content->text = get_string('selfcompletionnotenabled', 'block_selfcompletion'); } return $this->content; } // Check this user is enroled if (!$info->is_tracked_user($USER->id)) { $this->content->text = get_string('notenroled', 'completion'); return $this->content; } // Is course complete? if ($info->is_course_complete($USER->id)) { $this->content->text = get_string('coursealreadycompleted', 'completion'); return $this->content; // Check if the user has already marked themselves as complete } else { if ($completion->is_complete()) { $this->content->text = get_string('alreadyselfcompleted', 'block_selfcompletion'); return $this->content; // If user is not complete, or has not yet self completed } else { $this->content->text = ''; $this->content->footer = '<br /><a href="' . $CFG->wwwroot . '/course/togglecompletion.php?course=' . $this->page->course->id . '">'; $this->content->footer .= get_string('completecourse', 'block_selfcompletion') . '</a>...'; } } return $this->content; }
public function get_content() { global $USER; // If content is cached if ($this->content !== NULL) { return $this->content; } global $CFG; // Create empty content $this->content = new stdClass(); // Don't display if completion isn't enabled! if (!$this->page->course->enablecompletion) { $this->content->text = get_string('completionnotenabled', 'block_selfcompletion'); return $this->content; } // Get course completion data $info = new completion_info($this->page->course); $completion = $info->get_completion($USER->id, COMPLETION_CRITERIA_TYPE_SELF); // Is course complete? if ($info->is_course_complete($USER->id)) { return $this->content; } // Check if self completion is one of this course's criteria if (empty($completion)) { $this->content->text = get_string('selfcompletionnotenabled', 'block_selfcompletion'); return $this->content; } // Check this user is enroled if (!$info->is_tracked_user($USER->id)) { $this->content->text = get_string('notenroled', 'completion'); return $this->content; } // Check if the user has already marked themselves as complete if ($completion->is_complete()) { return $this->content; } else { $this->content->text = ''; $this->content->footer = '<br /><a href="' . $CFG->wwwroot . '/course/togglecompletion.php?course=' . $this->page->course->id . '">' . get_string('completecourse', 'block_selfcompletion') . '</a>...'; } return $this->content; }
echo html_writer::start_tag('tbody'); // If not display logged in user, show user name. if ($USER->id != $user->id) { echo html_writer::start_tag('tr'); echo html_writer::start_tag('td', array('colspan' => '2')); echo html_writer::tag('b', get_string('showinguser', 'completion')); $url = new moodle_url('/user/view.php', array('id' => $user->id, 'course' => $course->id)); echo html_writer::link($url, fullname($user)); echo html_writer::end_tag('td'); echo html_writer::end_tag('tr'); } echo html_writer::start_tag('tr'); echo html_writer::start_tag('td', array('colspan' => '2')); echo html_writer::tag('b', get_string('status')); // Is course complete? $coursecomplete = $info->is_course_complete($user->id); // Has this user completed any criteria? $criteriacomplete = $info->count_course_user_data($user->id); // Load course completion. $params = array('userid' => $user->id, 'course' => $course->id); $ccompletion = new completion_completion($params); if ($coursecomplete) { echo get_string('complete'); } else { if (!$criteriacomplete && !$ccompletion->timestarted) { echo html_writer::tag('i', get_string('notyetstarted', 'completion')); } else { echo html_writer::tag('i', get_string('inprogress', 'completion')); } } echo html_writer::end_tag('td');
/** * Performs the synchronisation of grades. * * @return bool|void */ public function execute() { global $DB, $CFG; require_once $CFG->dirroot . '/enrol/lti/ims-blti/OAuth.php'; require_once $CFG->dirroot . '/enrol/lti/ims-blti/OAuthBody.php'; require_once $CFG->dirroot . '/lib/completionlib.php'; require_once $CFG->libdir . '/gradelib.php'; require_once $CFG->dirroot . '/grade/querylib.php'; // Check if the authentication plugin is disabled. if (!is_enabled_auth('lti')) { mtrace('Skipping task - ' . get_string('pluginnotenabled', 'auth', get_string('pluginname', 'auth_lti'))); return true; } // Check if the enrolment plugin is disabled - isn't really necessary as the task should not run if // the plugin is disabled, but there is no harm in making sure core hasn't done something wrong. if (!enrol_is_enabled('lti')) { mtrace('Skipping task - ' . get_string('enrolisdisabled', 'enrol_lti')); return true; } // Get all the enabled tools. if ($tools = \enrol_lti\helper::get_lti_tools(array('status' => ENROL_INSTANCE_ENABLED, 'gradesync' => 1))) { foreach ($tools as $tool) { mtrace("Starting - Grade sync for shared tool '{$tool->id}' for the course '{$tool->courseid}'."); // Variables to keep track of information to display later. $usercount = 0; $sendcount = 0; // We check for all the users - users can access the same tool from different consumers. if ($ltiusers = $DB->get_records('enrol_lti_users', array('toolid' => $tool->id), 'lastaccess DESC')) { $completion = new \completion_info(get_course($tool->courseid)); foreach ($ltiusers as $ltiuser) { $mtracecontent = "for the user '{$ltiuser->userid}' in the tool '{$tool->id}' for the course " . "'{$tool->courseid}'"; $usercount = $usercount + 1; // Check if we do not have a serviceurl - this can happen if the sync process has an unexpected error. if (empty($ltiuser->serviceurl)) { mtrace("Skipping - Empty serviceurl {$mtracecontent}."); continue; } // Check if we do not have a sourceid - this can happen if the sync process has an unexpected error. if (empty($ltiuser->sourceid)) { mtrace("Skipping - Empty sourceid {$mtracecontent}."); continue; } // Need a valid context to continue. if (!($context = \context::instance_by_id($tool->contextid))) { mtrace("Failed - Invalid contextid '{$tool->contextid}' for the tool '{$tool->id}'."); continue; } // Ok, let's get the grade. $grade = false; if ($context->contextlevel == CONTEXT_COURSE) { // Check if the user did not completed the course when it was required. if ($tool->gradesynccompletion && !$completion->is_course_complete($ltiuser->userid)) { mtrace("Skipping - Course not completed {$mtracecontent}."); continue; } // Get the grade. if ($grade = grade_get_course_grade($ltiuser->userid, $tool->courseid)) { $grademax = floatval($grade->item->grademax); $grade = $grade->grade; } } else { if ($context->contextlevel == CONTEXT_MODULE) { $cm = get_coursemodule_from_id(false, $context->instanceid, 0, false, MUST_EXIST); if ($tool->gradesynccompletion) { $data = $completion->get_data($cm, false, $ltiuser->userid); if ($data->completionstate != COMPLETION_COMPLETE_PASS && $data->completionstate != COMPLETION_COMPLETE) { mtrace("Skipping - Activity not completed {$mtracecontent}."); continue; } } $grades = grade_get_grades($cm->course, 'mod', $cm->modname, $cm->instance, $ltiuser->userid); if (!empty($grades->items[0]->grades)) { $grade = reset($grades->items[0]->grades); if (!empty($grade->item)) { $grademax = floatval($grade->item->grademax); } else { $grademax = floatval($grades->items[0]->grademax); } $grade = $grade->grade; } } } if ($grade === false || $grade === null || strlen($grade) < 1) { mtrace("Skipping - Invalid grade {$mtracecontent}."); continue; } // No need to be dividing by zero. if (empty($grademax)) { mtrace("Skipping - Invalid grade {$mtracecontent}."); continue; } // This can happen if the sync process has an unexpected error. if ($grade == $ltiuser->lastgrade) { mtrace("Not sent - The grade {$mtracecontent} was not sent as the grades are the same."); continue; } // Sync with the external system. $floatgrade = $grade / $grademax; $body = \enrol_lti\helper::create_service_body($ltiuser->sourceid, $floatgrade); try { $response = sendOAuthBodyPOST('POST', $ltiuser->serviceurl, $ltiuser->consumerkey, $ltiuser->consumersecret, 'application/xml', $body); } catch (\Exception $e) { mtrace("Failed - The grade '{$floatgrade}' {$mtracecontent} failed to send."); mtrace($e->getMessage()); continue; } if (strpos(strtolower($response), 'success') !== false) { $DB->set_field('enrol_lti_users', 'lastgrade', intval($grade), array('id' => $ltiuser->id)); mtrace("Success - The grade '{$floatgrade}' {$mtracecontent} was sent."); $sendcount = $sendcount + 1; } else { mtrace("Failed - The grade '{$floatgrade}' {$mtracecontent} failed to send."); } } } mtrace("Completed - Synced grades for tool '{$tool->id}' in the course '{$tool->courseid}'. " . "Processed {$usercount} users; sent {$sendcount} grades."); mtrace(""); } } }
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; }
/** * 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; }
/** * Review this criteria and decide if it has been completed * * @return bool Whether criteria is complete */ public function review($userid) { global $DB; foreach ($this->params as $param) { $course = $DB->get_record('course', array('id' => $param['course'])); $info = new completion_info($course); $check_grade = true; $check_date = true; if (isset($param['grade'])) { $grade = grade_get_course_grade($userid, $course->id); $check_grade = $grade->grade >= $param['grade']; } if (isset($param['bydate'])) { $cparams = array('userid' => $userid, 'course' => $course->id); $completion = new completion_completion($cparams); $date = $completion->timecompleted; $check_date = $date <= $param['bydate']; } $overall = false; if ($this->method == BADGE_CRITERIA_AGGREGATION_ALL) { if ($info->is_course_complete($userid) && $check_grade && $check_date) { $overall = true; continue; } else { return false; } } else { if ($this->method == BADGE_CRITERIA_AGGREGATION_ANY) { if ($info->is_course_complete($userid) && $check_grade && $check_date) { return true; } else { $overall = false; continue; } } } } return $overall; }
/** * Review this criteria and decide if the user has completed * @access public * @param object $completion The user's completion record * @param boolean $mark Optionally set false to not save changes to database * @return boolean */ public function review($completion, $mark = true) { global $DB; $course = $DB->get_record('course', array('id' => $this->courseinstance)); $info = new completion_info($course); // If the course is complete if ($info->is_course_complete($completion->userid)) { if ($mark) { $completion->mark_complete(); } return true; } return false; }
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; }
} mtrace(" Sending grades for user {$user->userid}"); $user_count = $user_count + 1; // This can happen is the sync process has an unexpected error if (strlen($user->serviceurl) < 1) { mtrace(" Empty serviceurl"); continue; } if (strlen($user->sourceid) < 1) { mtrace(" Empty sourceid"); continue; } $grade = false; if ($context = $DB->get_record('context', array('id' => $tool->contextid))) { if ($context->contextlevel == CONTEXT_COURSE) { if ($tool->requirecompletion and !$completion->is_course_complete($user->userid)) { mtrace(" Skipping user {$user->userid} since he didn't complete the course"); continue; } if ($grade = grade_get_course_grade($user->userid, $tool->courseid)) { $grademax = floatval($grade->item->grademax); $grade = $grade->grade; } } else { if ($context->contextlevel == CONTEXT_MODULE) { $cm = get_coursemodule_from_id(false, $context->instanceid, 0, false, MUST_EXIST); if ($tool->requirecompletion) { $data = $completion->get_data($cm, false, $user->userid); if ($data->completionstate != COMPLETION_COMPLETE_PASS and $data->completionstate != COMPLETION_COMPLETE) { mtrace(" Skipping user {$user->userid} since he didn't complete the activity"); continue;
/** * Review this criteria and decide if it has been completed * * @param int $userid User whose criteria completion needs to be reviewed. * @param bool $filtered An additional parameter indicating that user list * has been reduced and some expensive checks can be skipped. * * @return bool Whether criteria is complete */ public function review($userid, $filtered = false) { $course = new stdClass(); $course->id = $this->courseid; if ($this->coursestartdate > time()) { return false; } $info = new completion_info($course); foreach ($this->params as $param) { $check_grade = true; $check_date = true; if (isset($param['grade'])) { $grade = grade_get_course_grade($userid, $course->id); $check_grade = $grade->grade >= $param['grade']; } if (!$filtered && isset($param['bydate'])) { $cparams = array('userid' => $userid, 'course' => $course->id); $completion = new completion_completion($cparams); $date = $completion->timecompleted; $check_date = $date <= $param['bydate']; } if ($info->is_course_complete($userid) && $check_grade && $check_date) { return true; } } return false; }
/** * Review this criteria and decide if it has been completed * * @param int $userid User whose criteria completion needs to be reviewed. * @return bool Whether criteria is complete */ public function review($userid) { global $DB; foreach ($this->params as $param) { $course = $DB->get_record('course', array('id' => $param['course'])); if ($course->startdate > time()) { return false; } $info = new completion_info($course); $check_grade = true; $check_date = true; if (isset($param['grade'])) { $grade = grade_get_course_grade($userid, $course->id); $check_grade = $grade->grade >= $param['grade']; } if (isset($param['bydate'])) { $cparams = array('userid' => $userid, 'course' => $course->id); $completion = new completion_completion($cparams); $date = $completion->timecompleted; $check_date = $date <= $param['bydate']; } if ($info->is_course_complete($userid) && $check_grade && $check_date) { return true; } } return false; }
/** * Cron function for sync grades * @return void */ function local_ltiprovider_cron() { global $DB, $CFG; require_once $CFG->dirroot . "/local/ltiprovider/locallib.php"; require_once $CFG->dirroot . "/local/ltiprovider/ims-blti/OAuth.php"; require_once $CFG->dirroot . "/local/ltiprovider/ims-blti/OAuthBody.php"; require_once $CFG->libdir . '/gradelib.php'; require_once $CFG->dirroot . '/grade/querylib.php'; // TODO - Add a global setting for this $synctime = 60 * 60; // Every 1 hour grades are sync $timenow = time(); mtrace('Running cron for ltiprovider'); mtrace('Deleting LTI tools assigned to deleted courses'); if ($tools = $DB->get_records('local_ltiprovider')) { foreach ($tools as $tool) { local_ltiprovider_check_missing_course($tool); } } // Grades service. if ($tools = $DB->get_records_select('local_ltiprovider', 'disabled = ? AND sendgrades = ?', array(0, 1))) { foreach ($tools as $tool) { if ($tool->lastsync + $synctime < $timenow) { mtrace(" Starting sync tool for grades id {$tool->id} course id {$tool->courseid}"); if ($tool->requirecompletion) { mtrace(" Grades require activity or course completion"); } $user_count = 0; $send_count = 0; $error_count = 0; $completion = new completion_info(get_course($tool->courseid)); if ($users = $DB->get_records('local_ltiprovider_user', array('toolid' => $tool->id))) { foreach ($users as $user) { $user_count = $user_count + 1; // This can happen is the sync process has an unexpected error if (strlen($user->serviceurl) < 1) { mtrace(" Empty serviceurl"); continue; } if (strlen($user->sourceid) < 1) { mtrace(" Empty sourceid"); continue; } if ($user->lastsync > $tool->lastsync) { mtrace(" Skipping user {$user->id} due to recent sync"); continue; } $grade = false; if ($context = $DB->get_record('context', array('id' => $tool->contextid))) { if ($context->contextlevel == CONTEXT_COURSE) { if ($tool->requirecompletion and !$completion->is_course_complete($user->userid)) { mtrace(" Skipping user {$user->userid} since he didn't complete the course"); continue; } if ($grade = grade_get_course_grade($user->userid, $tool->courseid)) { $grademax = floatval($grade->item->grademax); $grade = $grade->grade; } } else { if ($context->contextlevel == CONTEXT_MODULE) { $cm = get_coursemodule_from_id(false, $context->instanceid, 0, false, MUST_EXIST); if ($tool->requirecompletion) { $data = $completion->get_data($cm, false, $user->userid); if ($data->completionstate != COMPLETION_COMPLETE_PASS and $data->completionstate != COMPLETION_COMPLETE) { mtrace(" Skipping user {$user->userid} since he didn't complete the activity"); continue; } } $grades = grade_get_grades($cm->course, 'mod', $cm->modname, $cm->instance, $user->userid); if (empty($grades->items[0]->grades)) { $grade = false; } else { $grade = reset($grades->items[0]->grades); if (!empty($grade->item)) { $grademax = floatval($grade->item->grademax); } else { $grademax = floatval($grades->items[0]->grademax); } $grade = $grade->grade; } } } if ($grade === false || $grade === NULL || strlen($grade) < 1) { mtrace(" Invalid grade {$grade}"); continue; } // No need to be dividing by zero if ($grademax == 0.0) { $grademax = 100.0; } // TODO: Make lastgrade should be float or string - but it is integer so we truncate // TODO: Then remove those intval() calls // Don't double send if (intval($grade) == $user->lastgrade) { mtrace(" Skipping, last grade send is equal to current grade"); continue; } // We sync with the external system only when the new grade differs with the previous one // TODO - Global setting for check this if ($grade >= 0 and $grade <= $grademax) { $float_grade = $grade / $grademax; $body = local_ltiprovider_create_service_body($user->sourceid, $float_grade); try { $response = ltiprovider\sendOAuthBodyPOST('POST', $user->serviceurl, $user->consumerkey, $user->consumersecret, 'application/xml', $body); } catch (Exception $e) { mtrace(" " . $e->getMessage()); $error_count = $error_count + 1; continue; } // TODO - Check for errors in $retval in a correct way (parsing xml) if (strpos(strtolower($response), 'success') !== false) { $DB->set_field('local_ltiprovider_user', 'lastsync', $timenow, array('id' => $user->id)); $DB->set_field('local_ltiprovider_user', 'lastgrade', intval($grade), array('id' => $user->id)); mtrace(" User grade sent to remote system. userid: {$user->userid} grade: {$float_grade}"); $send_count = $send_count + 1; } else { mtrace(" User grade send failed. userid: {$user->userid} grade: {$float_grade}: " . $response); $error_count = $error_count + 1; } } else { mtrace(" User grade for user {$user->userid} out of range: grade = " . $grade); $error_count = $error_count + 1; } } else { mtrace(" Invalid context: contextid = " . $tool->contextid); } } } mtrace(" Completed sync tool id {$tool->id} course id {$tool->courseid} users={$user_count} sent={$send_count} errors={$error_count}"); $DB->set_field('local_ltiprovider', 'lastsync', $timenow, array('id' => $tool->id)); } } } $timenow = time(); // Automatic course restaurations. if ($croncourses = get_config('local_ltiprovider', 'croncourses')) { $croncourses = unserialize($croncourses); if (is_array($croncourses)) { mtrace('Starting restauration of pending courses'); foreach ($croncourses as $key => $course) { mtrace('Starting restoration of ' . $key); // We limit the backups to 1 hour, then retry. if ($course->restorestart and $timenow < $course->restorestart + 3600) { mtrace('Skipping restoration in process for: ' . $key); continue; } $course->restorestart = time(); $croncourses[$key] = $course; $croncoursessafe = serialize($croncourses); set_config('croncourses', $croncoursessafe, 'local_ltiprovider'); if ($destinationcourse = $DB->get_record('course', array('id' => $course->destinationid))) { // Duplicate course + users. local_ltiprovider_duplicate_course($course->id, $destinationcourse, 1, $options = array(array('name' => 'users', 'value' => 1)), $course->userrestoringid, $course->context); mtrace('Restoration for ' . $key . ' finished'); } else { mtrace('Restoration for ' . $key . ' finished (destination course not exists)'); } unset($croncourses[$key]); $croncoursessafe = serialize($croncourses); set_config('croncourses', $croncoursessafe, 'local_ltiprovider'); } } } // Membership service. $timenow = time(); $userphotos = array(); if ($tools = $DB->get_records('local_ltiprovider', array('disabled' => 0, 'syncmembers' => 1))) { mtrace('Starting sync of member using the memberships service'); $consumers = array(); foreach ($tools as $tool) { $lastsync = get_config('local_ltiprovider', 'membershipslastsync-' . $tool->id); if (!$lastsync) { $lastsync = 0; } if ($lastsync + $tool->syncperiod < $timenow) { mtrace('Starting sync of tool: ' . $tool->id); // We check for all the users, notice that users can access the same tool from different consumers. if ($users = $DB->get_records('local_ltiprovider_user', array('toolid' => $tool->id), 'lastaccess DESC')) { $response = ""; foreach ($users as $user) { if (!$user->membershipsurl or !$user->membershipsid) { continue; } $consumer = md5($user->membershipsurl . ':' . $user->membershipsid . ':' . $user->consumerkey . ':' . $user->consumersecret); if (in_array($consumer, $consumers)) { // We had syncrhonized with this consumer yet. continue; } $consumers[] = $consumer; $params = array('lti_message_type' => 'basic-lis-readmembershipsforcontext', 'id' => $user->membershipsid, 'lti_version' => 'LTI-1p0'); mtrace('Calling memberships url: ' . $user->membershipsurl . ' with body: ' . json_encode($params)); try { $response = ltiprovider\sendOAuthParamsPOST('POST', $user->membershipsurl, $user->consumerkey, $user->consumersecret, 'application/x-www-form-urlencoded', $params); } catch (Exception $e) { mtrace("Exception: " . $e->getMessage()); $response = false; } if ($response) { $data = new SimpleXMLElement($response); if (!empty($data->statusinfo)) { if (strpos(strtolower($data->statusinfo->codemajor), 'success') !== false) { $members = $data->memberships->member; mtrace(count($members) . ' members received'); $currentusers = array(); foreach ($members as $member) { $username = local_ltiprovider_create_username($user->consumerkey, $member->user_id); $userobj = $DB->get_record('user', array('username' => $username)); if (!$userobj) { // Old format. $oldusername = '******' . md5($user->consumerkey . ':' . $member->user_id); $userobj = $DB->get_record('user', array('username' => $oldusername)); if ($userobj) { $DB->set_field('user', 'username', $username, array('id' => $userobj->id)); } $userobj = $DB->get_record('user', array('username' => $username)); } if ($userobj) { $currentusers[] = $userobj->id; $userobj->firstname = clean_param($member->person_name_given, PARAM_TEXT); $userobj->lastname = clean_param($member->person_name_family, PARAM_TEXT); $userobj->email = clean_param($member->person_contact_email_primary, PARAM_EMAIL); $userobj->timemodified = time(); $DB->update_record('user', $userobj); $userphotos[$userobj->id] = $member->user_image; // Trigger event. $event = \core\event\user_updated::create(array('objectid' => $userobj->id, 'relateduserid' => $userobj->id, 'context' => context_user::instance($userobj->id))); $event->trigger(); } else { // New members. if ($tool->syncmode == 1 or $tool->syncmode == 2) { // We have to enrol new members so we have to create it. $userobj = new stdClass(); // clean_param , email username text $auth = get_config('local_ltiprovider', 'defaultauthmethod'); if ($auth) { $userobj->auth = $auth; } else { $userobj->auth = 'nologin'; } $username = local_ltiprovider_create_username($user->consumerkey, $member->user_id); $userobj->username = $username; $userobj->password = md5(uniqid(rand(), 1)); $userobj->firstname = clean_param($member->person_name_given, PARAM_TEXT); $userobj->lastname = clean_param($member->person_name_family, PARAM_TEXT); $userobj->email = clean_param($member->person_contact_email_primary, PARAM_EMAIL); $userobj->city = $tool->city; $userobj->country = $tool->country; $userobj->institution = $tool->institution; $userobj->timezone = $tool->timezone; $userobj->maildisplay = $tool->maildisplay; $userobj->mnethostid = $CFG->mnet_localhost_id; $userobj->confirmed = 1; $userobj->lang = $tool->lang; $userobj->timecreated = time(); if (!$userobj->lang) { // TODO: This should be changed for detect the course lang $userobj->lang = current_language(); } $userobj->id = $DB->insert_record('user', $userobj); // Reload full user $userobj = $DB->get_record('user', array('id' => $userobj->id)); $userphotos[$userobj->id] = $member->user_image; // Trigger event. $event = \core\event\user_created::create(array('objectid' => $userobj->id, 'relateduserid' => $userobj->id, 'context' => context_user::instance($userobj->id))); $event->trigger(); $currentusers[] = $userobj->id; } } // 1 -> Enrol and unenrol, 2 -> enrol if ($tool->syncmode == 1 or $tool->syncmode == 2) { // Enroll the user in the course. We don't know if it was previously unenrolled. $roles = explode(',', strtolower($member->roles)); local_ltiprovider_enrol_user($tool, $userobj, $roles, true); } } // Now we check if we have to unenrol users for keep both systems sync. if ($tool->syncmode == 1 or $tool->syncmode == 3) { // Unenrol users also. $context = context_course::instance($tool->courseid); $eusers = get_enrolled_users($context); foreach ($eusers as $euser) { if (!in_array($euser->id, $currentusers)) { local_ltiprovider_unenrol_user($tool, $euser); } } } } else { mtrace('Error recived from the remote system: ' . $data->statusinfo->codemajor . ' ' . $data->statusinfo->severity . ' ' . $data->statusinfo->codeminor); } } else { mtrace('Error parsing the XML received' . substr($response, 0, 125) . '... (Displaying only 125 chars)'); } } else { mtrace('No response received from ' . $user->membershipsurl); } } } set_config('membershipslastsync-' . $tool->id, $timenow, 'local_ltiprovider'); } else { $last = format_time(time() - $lastsync); mtrace("Tool {$tool->id} synchronized {$last} ago"); } mtrace('Finished sync of member using the memberships service'); } } // Sync of user photos. mtrace("Sync user profile images"); $counter = 0; if ($userphotos) { foreach ($userphotos as $userid => $url) { if ($url) { $result = local_ltiprovider_update_user_profile_image($userid, $url); if ($result === true) { $counter++; mtrace("Profile image succesfully downloaded and created from {$url}"); } else { mtrace($result); } } } } mtrace("{$counter} profile images updated"); }
public function get_content() { global $USER, $CFG, $DB, $COURSE; if ($this->content !== null) { return $this->content; } $this->content = new stdClass(); $courses1 = enrol_get_my_courses('', 'visible DESC,sortorder ASC'); //defined in lib/enrollib.php file // Display completion status $this->content->text .= '<table cellpadding="0" cellspacing="0" width="178" border="0">'; $this->content->text .= '<tr>'; $this->content->text .= '<td width="85" align="right"><b>Total</b>'; $this->content->text .= '</td><td align="left"><b>Over</b>'; $this->content->text .= '</td><td align="left"><b>%</b>'; $this->content->text .= '</td></tr></table>'; $this->content->text .= '<table cellpadding="0" cellspacing="0" width="178" border="0">'; foreach ($courses1 as $course1) { if ($course1->id == SITEID) { continue; } $userid = optional_param('user', 0, PARAM_INT); // Load course $course = $DB->get_record('course', array('id' => $course1->id)); // Load user if ($userid) { $user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST); } else { $user = $USER; } $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id); $personalcontext = get_context_instance(CONTEXT_USER, $user->id); $can_view = false; // Can view own report if ($USER->id == $user->id) { $can_view = true; } else { if (has_capability('moodle/user:viewuseractivitiesreport', $personalcontext)) { $can_view = true; } else { if (has_capability('coursereport/completion:view', $coursecontext)) { $can_view = true; } else { if (has_capability('coursereport/completion:view', $personalcontext)) { $can_view = true; } } } } if (!$can_view) { $this->content->text .= print_error('cannotviewreport'); } // Load completion data $info = new completion_info($course); // Load criteria to display $completions = $info->get_completions($user->id); // Check this user is enroled if (!$info->is_tracked_user($user->id)) { if ($USER->id == $user->id) { $this->content->text .= print_error('notenroled', 'completion', $returnurl); } else { $this->content->text .= print_error('usernotenroled', 'completion', $returnurl); } } // Is course complete? $coursecomplete = $info->is_course_complete($user->id); // Has this user completed any criteria? $criteriacomplete = $info->count_course_user_data($user->id); if ($coursecomplete) { $status = get_string('complete'); } else { if (!$criteriacomplete) { $status = '<i>' . get_string('notyetstarted', 'completion') . '</i>'; } else { $status = '<i>' . get_string('inprogress', 'completion') . '</i>'; } } //GET TOTAL NUMBER OF TASKS ASSIGNED TO CURRENT USER $conditions = array("course" => $course->id); $tot_rec = $DB->count_records('course_completion_criteria', $conditions); //GET TOTAL NUMBER OF TASKS ASSIGNED TO CURRENT USER $result = $DB->get_records_sql('SELECT mc.coursemoduleid,mc.userid,mc.completionstate, m.id,m.course FROM `mdl_course_modules_completion` mc LEFT JOIN mdl_course_modules m ON mc.coursemoduleid=m.id WHERE mc.userid = ? AND m.course = ?', array($user->id, $course->id)); $tot_comp = count($result); $count1 = $tot_comp / $tot_rec; $count2 = $count1 * 100; $count = number_format($count2, 0); $linkhref = new moodle_url('/course/view.php', array('id' => $course->id)); $this->content->text .= '<tr><td colspan="4"><b title="Course" style="color:#000066;">'; $this->content->text .= '<a href="' . $linkhref . '">' . $course1->fullname . '</a>'; $this->content->text .= '</b></td></tr>'; $this->content->text .= '<tr><td align="left" width="70" title="Activity completion status">'; //$this->content->text .=$course1->fullname; $this->content->text .= $status; $this->content->text .= '</td><td align="left" width="27" title="Total activities">' . $tot_rec; $this->content->text .= '</td><td width="27" align="left" title="Total Activities completed">' . $tot_comp; $this->content->text .= '</td><td width="26" align="right" title="Activities completed(%)">' . $count . '%'; $this->content->text .= '</td></tr>'; } $this->content->text .= '</table>'; //$this->content->footer .= 'Footer here...'; return $this->content; }
/** * Construct contents of course_overview block * * @param array $courses list of courses in sorted order * @param array $overviews list of course overviews * @return string html to be displayed in course_overview block */ public function course_overview($courses, $overviews) { $html = ''; $config = get_config('block_course_overview'); $ismovingcourse = false; $courseordernumber = 0; $maxcourses = count($courses); $userediting = false; // Intialise string/icon etc if user is editing and courses > 1 if ($this->page->user_is_editing() && count($courses) > 1) { $userediting = true; $this->page->requires->js_init_call('M.block_course_overview.add_handles'); // Check if course is moving $ismovingcourse = optional_param('movecourse', FALSE, PARAM_BOOL); $movingcourseid = optional_param('courseid', 0, PARAM_INT); } // Render first movehere icon. if ($ismovingcourse) { // Remove movecourse param from url. $this->page->ensure_param_not_in_url('movecourse'); // Show moving course notice, so user knows what is being moved. $html .= $this->output->box_start('notice'); $a = new stdClass(); $a->fullname = $courses[$movingcourseid]->fullname; $a->cancellink = html_writer::link($this->page->url, get_string('cancel')); $html .= get_string('movingcourse', 'block_course_overview', $a); $html .= $this->output->box_end(); $moveurl = new moodle_url('/blocks/course_overview/move.php', array('sesskey' => sesskey(), 'moveto' => 0, 'courseid' => $movingcourseid)); // Create move icon, so it can be used. $movetofirsticon = html_writer::empty_tag('img', array('src' => $this->output->pix_url('movehere'), 'alt' => get_string('movetofirst', 'block_course_overview', $courses[$movingcourseid]->fullname), 'title' => get_string('movehere'))); $moveurl = html_writer::link($moveurl, $movetofirsticon); $html .= html_writer::tag('div', $moveurl, array('class' => 'movehere')); } $completedcourseshtml = ''; $inprogresscourseshtml = ''; $coursehtmlrecord = ''; foreach ($courses as $key => $course) { $coursehtmlrecord = ''; // If moving course, then don't show course which needs to be moved. if ($ismovingcourse && $course->id == $movingcourseid) { continue; } $coursehtmlrecord .= $this->output->box_start('coursebox', "course-{$course->id}"); $coursehtmlrecord .= html_writer::start_tag('div', array('class' => 'course_title')); // If user is editing, then add move icons. //GWL Display course image - Start global $CFG, $DB, $USER; $course = new course_in_list($course); //Getting progress percentage. $progress = get_course_progress_percentage($course, $USER); $completionstate = get_course_lesson_completionstate($course); $info = new completion_info($course); //GWL - Add this to add contion to generate certificate when instructor mark completed $completionstate = $info->is_course_complete($USER->id); //GWL - Add this to add contion to generate certificate when instructor mark completed // display course overview files $contentimages = $contentfiles = ''; foreach ($course->get_course_overviewfiles() as $file) { $isimage = $file->is_valid_image(); $url = file_encode_url("{$CFG->wwwroot}/pluginfile.php", '/' . $file->get_contextid() . '/' . $file->get_component() . '/' . $file->get_filearea() . $file->get_filepath() . $file->get_filename(), !$isimage); if ($isimage) { $contentimages .= html_writer::tag('div', html_writer::empty_tag('img', array('src' => $url)), array('class' => 'courseimage')); } else { $image = $this->output->pix_icon(file_file_icon($file, 24), $file->get_filename(), 'moodle'); $filename = html_writer::tag('span', $image, array('class' => 'fp-icon')) . html_writer::tag('span', $file->get_filename(), array('class' => 'fp-filename')); $contentfiles .= html_writer::tag('span', html_writer::link($url, $filename), array('class' => 'coursefile fp-filename-icon')); } } $content .= $contentimages . $contentfiles; $coursehtmlrecord .= $content; $attributes = array('title' => $course->fullname); if ($course->id > 0) { if (empty($course->visible)) { $attributes['class'] = 'dimmed'; } $courseurl = new moodle_url('/course/view.php', array('id' => $course->id)); $lession_id = get_course_lesson_id($course); if ($lession_id) { $courseurl = new moodle_url('/mod/lesson/view.php', array('id' => $lession_id)); } $coursefullname = format_string(get_course_display_name_for_list($course), true, $course->id); $link = html_writer::link($courseurl, $coursefullname, $attributes); if ($progress >= 100 || $completionstate == 1) { $coursehtmlrecord .= $this->output->heading($coursefullname, 2, 'title'); } else { $coursehtmlrecord .= $this->output->heading($link, 2, 'title'); } } else { $coursehtmlrecord .= $this->output->heading(html_writer::link(new moodle_url('/auth/mnet/jump.php', array('hostid' => $course->hostid, 'wantsurl' => '/course/view.php?id=' . $course->remoteid)), format_string($course->shortname, true), $attributes) . ' (' . format_string($course->hostname) . ')', 2, 'title'); } $result = $DB->get_field("course", "summary", array("id" => $course->id)); $coursehtmlrecord .= $result; //GWL Display course image - END //GWL to get download certificate link if ($progress < 100 && !$completionstate) { $coursehtmlrecord .= '<div style=" background-color: #ccc; color: #fff; text-align: right; vertical-align: middle; height: 20px; border-radius: 10px; overflow: hidden; margin-bottom: 5px;"><div style="width: ' . $progress . '%; float: left; background-color: green; padding-right: 10px;">' . $progress . '%</div></div>'; } else { $certificates = get_coursemodules_in_course('iomadcertificate', $course->id); $certificatelink = '-'; if ($certificates) { $showcertificate = 1; foreach ($certificates as $certficate) { $modinfo = get_fast_modinfo($course->id); $cm = $modinfo->get_cm($certficate->id); if ($cm && $cm->uservisible) { $coursehtmlrecord .= '<div><a href="' . $CFG->wwwroot . '/mod/iomadcertificate/view.php?id=' . $certficate->id . '&action=get" class="pull-right" style="color:#f5811e;"> <i class="fa fa-cloud-download" style="color:#f5811e;" ></i> Download Certificate</a> </div>'; } } } } //GWL to get download certificate link // GWL - Course Status On Dashboard / if ($userediting && !$ismovingcourse) { $moveicon = html_writer::empty_tag('img', array('src' => $this->pix_url('t/move')->out(false), 'alt' => get_string('movecourse', 'block_course_overview', $course->fullname), 'title' => get_string('move'))); $moveurl = new moodle_url($this->page->url, array('sesskey' => sesskey(), 'movecourse' => 1, 'courseid' => $course->id)); $moveurl = html_writer::link($moveurl, $moveicon); $coursehtmlrecord .= html_writer::tag('div', $moveurl, array('class' => 'move')); } // No need to pass title through s() here as it will be done automatically by html_writer. $coursehtmlrecord .= $this->output->box('', 'flush'); $coursehtmlrecord .= html_writer::end_tag('div'); if (!empty($config->showchildren) && $course->id > 0) { // List children here. if ($children = block_course_overview_get_child_shortnames($course->id)) { $coursehtmlrecord .= html_writer::tag('span', $children, array('class' => 'coursechildren')); } } // If user is moving courses, then down't show overview. if (isset($overviews[$course->id]) && !$ismovingcourse) { $coursehtmlrecord .= $this->activity_display($course->id, $overviews[$course->id]); } $coursehtmlrecord .= $this->output->box('', 'flush'); $coursehtmlrecord .= $this->output->box_end(); $courseordernumber++; if ($ismovingcourse) { $moveurl = new moodle_url('/blocks/course_overview/move.php', array('sesskey' => sesskey(), 'moveto' => $courseordernumber, 'courseid' => $movingcourseid)); $a = new stdClass(); $a->movingcoursename = $courses[$movingcourseid]->fullname; $a->currentcoursename = $course->fullname; $movehereicon = html_writer::empty_tag('img', array('src' => $this->output->pix_url('movehere'), 'alt' => get_string('moveafterhere', 'block_course_overview', $a), 'title' => get_string('movehere'))); $moveurl = html_writer::link($moveurl, $movehereicon); $coursehtmlrecord .= html_writer::tag('div', $moveurl, array('class' => 'movehere')); } if ($progress >= 100 || $completionstate == 1) { $completedcourseshtml .= $coursehtmlrecord; } else { $inprogresscourseshtml .= $coursehtmlrecord; } } $html .= '<div class="inprogresscourse">In Progress Courses</div>'; $html .= $inprogresscourseshtml; $html .= '<div class="completecourse">Completed Courses</div>'; $html .= $completedcourseshtml; // Wrap course list in a div and return. return html_writer::tag('div', $html, array('class' => 'course_list')); }