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;
 }
Exemple #4
0
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');
Exemple #5
0
 /**
  * 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;
 }
Exemple #7
0
 /**
  * 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;
 }
Exemple #14
0
/**
 * 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'));
    }