mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 00:12:56 +02:00
Merge branch 'wip-mdl-39955' of git://github.com/rajeshtaneja/moodle
This commit is contained in:
commit
969de2a200
108
badges/classes/observer.php
Normal file
108
badges/classes/observer.php
Normal file
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Local stuff for category enrolment plugin.
|
||||
*
|
||||
* @package core_badges
|
||||
* @copyright 2013 Rajesh Taneja <rajesh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Event observer for badges.
|
||||
*/
|
||||
class core_badges_observer {
|
||||
/**
|
||||
* Triggered when 'course_module_completion_updated' event is triggered.
|
||||
*
|
||||
* @param \core\event\course_module_completion_updated $event
|
||||
*/
|
||||
public static function course_module_criteria_review(\core\event\course_module_completion_updated $event) {
|
||||
global $DB, $CFG;
|
||||
|
||||
if (!empty($CFG->enablebadges)) {
|
||||
require_once($CFG->dirroot.'/lib/badgeslib.php');
|
||||
|
||||
$eventdata = $event->get_record_snapshot('course_modules_completion', $event->objectid);
|
||||
$userid = $event->other['relateduserid'];
|
||||
$mod = $eventdata->coursemoduleid;
|
||||
|
||||
if ($eventdata->completionstate == COMPLETION_COMPLETE
|
||||
|| $eventdata->completionstate == COMPLETION_COMPLETE_PASS
|
||||
|| $eventdata->completionstate == COMPLETION_COMPLETE_FAIL) {
|
||||
// Need to take into account that there can be more than one badge with the same activity in its criteria.
|
||||
if ($rs = $DB->get_records('badge_criteria_param', array('name' => 'module_' . $mod, 'value' => $mod))) {
|
||||
foreach ($rs as $r) {
|
||||
$bid = $DB->get_field('badge_criteria', 'badgeid', array('id' => $r->critid), MUST_EXIST);
|
||||
$badge = new badge($bid);
|
||||
if (!$badge->is_active() || $badge->is_issued($userid)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($badge->criteria[BADGE_CRITERIA_TYPE_ACTIVITY]->review($userid)) {
|
||||
$badge->criteria[BADGE_CRITERIA_TYPE_ACTIVITY]->mark_complete($userid);
|
||||
|
||||
if ($badge->criteria[BADGE_CRITERIA_TYPE_OVERALL]->review($userid)) {
|
||||
$badge->criteria[BADGE_CRITERIA_TYPE_OVERALL]->mark_complete($userid);
|
||||
$badge->issue($userid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when 'course_completed' event is triggered.
|
||||
*
|
||||
* @param \core\event\course_completed $event
|
||||
*/
|
||||
public static function course_criteria_review(\core\event\course_completed $event) {
|
||||
global $DB, $CFG;
|
||||
|
||||
if (!empty($CFG->enablebadges)) {
|
||||
require_once($CFG->dirroot.'/lib/badgeslib.php');
|
||||
|
||||
$eventdata = $event->get_record_snapshot('course_completions', $event->objectid);
|
||||
$userid = $event->other['relateduserid'];
|
||||
$courseid = $event->courseid;
|
||||
|
||||
// Need to take into account that course can be a part of course_completion and courseset_completion criteria.
|
||||
if ($rs = $DB->get_records('badge_criteria_param', array('name' => 'course_' . $courseid, 'value' => $courseid))) {
|
||||
foreach ($rs as $r) {
|
||||
$crit = $DB->get_record('badge_criteria', array('id' => $r->critid), 'badgeid, criteriatype', MUST_EXIST);
|
||||
$badge = new badge($crit->badgeid);
|
||||
if (!$badge->is_active() || $badge->is_issued($userid)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($badge->criteria[$crit->criteriatype]->review($userid)) {
|
||||
$badge->criteria[$crit->criteriatype]->mark_complete($userid);
|
||||
|
||||
if ($badge->criteria[BADGE_CRITERIA_TYPE_OVERALL]->review($userid)) {
|
||||
$badge->criteria[BADGE_CRITERIA_TYPE_OVERALL]->mark_complete($userid);
|
||||
$badge->issue($userid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -31,9 +31,13 @@ require_once($CFG->libdir . '/badgeslib.php');
|
||||
|
||||
class core_badgeslib_testcase extends advanced_testcase {
|
||||
protected $badgeid;
|
||||
protected $course;
|
||||
protected $user;
|
||||
protected $module;
|
||||
protected $coursebadge;
|
||||
|
||||
protected function setUp() {
|
||||
global $DB;
|
||||
global $DB, $CFG;
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
@ -59,6 +63,29 @@ class core_badgeslib_testcase extends advanced_testcase {
|
||||
$fordb->status = BADGE_STATUS_INACTIVE;
|
||||
|
||||
$this->badgeid = $DB->insert_record('badge', $fordb, true);
|
||||
|
||||
// Create a course with activity and auto completion tracking.
|
||||
$this->course = $this->getDataGenerator()->create_course();
|
||||
$this->user = $this->getDataGenerator()->create_user();
|
||||
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
|
||||
$this->assertNotEmpty($studentrole);
|
||||
|
||||
// Get manual enrolment plugin and enrol user.
|
||||
require_once($CFG->dirroot.'/enrol/manual/locallib.php');
|
||||
$manplugin = enrol_get_plugin('manual');
|
||||
$maninstance = $DB->get_record('enrol', array('courseid' => $this->course->id, 'enrol' => 'manual'), '*', MUST_EXIST);
|
||||
$manplugin->enrol_user($maninstance, $this->user->id, $studentrole->id);
|
||||
$this->assertEquals(1, $DB->count_records('user_enrolments'));
|
||||
|
||||
$completionauto = array('completion' => COMPLETION_TRACKING_AUTOMATIC);
|
||||
$this->module = $this->getDataGenerator()->create_module('forum', array('course' => $this->course->id), $completionauto);
|
||||
|
||||
// Build badge and criteria.
|
||||
$fordb->type = BADGE_TYPE_COURSE;
|
||||
$fordb->courseid = $this->course->id;
|
||||
$fordb->status = BADGE_STATUS_ACTIVE;
|
||||
|
||||
$this->coursebadge = $DB->insert_record('badge', $fordb, true);
|
||||
}
|
||||
|
||||
public function test_create_badge() {
|
||||
@ -183,4 +210,54 @@ class core_badgeslib_testcase extends advanced_testcase {
|
||||
$this->assertEquals(badge_message_from_template($message, $params), $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test badges observer when course module completion event id fired.
|
||||
*/
|
||||
public function test_badges_observer_course_module_criteria_review() {
|
||||
$badge = new badge($this->coursebadge);
|
||||
$this->assertFalse($badge->is_issued($this->user->id));
|
||||
|
||||
$criteria_overall = award_criteria::build(array('criteriatype' => BADGE_CRITERIA_TYPE_OVERALL, 'badgeid' => $badge->id));
|
||||
$criteria_overall->save(array('agg' => BADGE_CRITERIA_AGGREGATION_ANY));
|
||||
$criteria_overall = award_criteria::build(array('criteriatype' => BADGE_CRITERIA_TYPE_ACTIVITY, 'badgeid' => $badge->id));
|
||||
$criteria_overall->save(array('agg' => BADGE_CRITERIA_AGGREGATION_ANY, 'module_'.$this->module->id => $this->module->id));
|
||||
|
||||
// Set completion for forum activity.
|
||||
$c = new completion_info($this->course);
|
||||
$activities = $c->get_activities();
|
||||
$this->assertEquals(1, count($activities));
|
||||
$this->assertTrue(isset($activities[$this->module->cmid]));
|
||||
$this->assertEquals($activities[$this->module->cmid]->name, $this->module->name);
|
||||
|
||||
$current = $c->get_data($activities[$this->module->cmid], false, $this->user->id);
|
||||
$current->completionstate = COMPLETION_COMPLETE;
|
||||
$current->timemodified = time();
|
||||
$c->internal_set_data($activities[$this->module->cmid], $current);
|
||||
|
||||
// Check if badge is awarded.
|
||||
$this->assertDebuggingCalled('Error baking badge image!');
|
||||
$this->assertTrue($badge->is_issued($this->user->id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test badges observer when course_completed event is fired.
|
||||
*/
|
||||
public function test_badges_observer_course_criteria_review() {
|
||||
$badge = new badge($this->coursebadge);
|
||||
$this->assertFalse($badge->is_issued($this->user->id));
|
||||
|
||||
$criteria_overall = award_criteria::build(array('criteriatype' => BADGE_CRITERIA_TYPE_OVERALL, 'badgeid' => $badge->id));
|
||||
$criteria_overall->save(array('agg' => BADGE_CRITERIA_AGGREGATION_ANY));
|
||||
$criteria_overall1 = award_criteria::build(array('criteriatype' => BADGE_CRITERIA_TYPE_COURSE, 'badgeid' => $badge->id));
|
||||
$criteria_overall1->save(array('agg' => BADGE_CRITERIA_AGGREGATION_ANY, 'course_'.$this->course->id => $this->course->id));
|
||||
|
||||
$ccompletion = new completion_completion(array('course' => $this->course->id, 'userid' => $this->user->id));
|
||||
|
||||
// Mark course as complete.
|
||||
$ccompletion->mark_complete();
|
||||
|
||||
// Check if badge is awarded.
|
||||
$this->assertDebuggingCalled('Error baking badge image!');
|
||||
$this->assertTrue($badge->is_issued($this->user->id));
|
||||
}
|
||||
}
|
||||
|
@ -143,23 +143,35 @@ class completion_completion extends data_object {
|
||||
* @return void
|
||||
*/
|
||||
public function mark_complete($timecomplete = null) {
|
||||
global $USER;
|
||||
|
||||
// Never change a completion time
|
||||
// Never change a completion time.
|
||||
if ($this->timecompleted) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Use current time if nothing supplied
|
||||
// Use current time if nothing supplied.
|
||||
if (!$timecomplete) {
|
||||
$timecomplete = time();
|
||||
}
|
||||
|
||||
// Set time complete
|
||||
// Set time complete.
|
||||
$this->timecompleted = $timecomplete;
|
||||
|
||||
// Save record
|
||||
// Save record.
|
||||
if ($result = $this->_save()) {
|
||||
events_trigger('course_completed', $this->get_record_data());
|
||||
$data = $this->get_record_data();
|
||||
$event = \core\event\course_completed::create(
|
||||
array(
|
||||
'objectid' => $data->id,
|
||||
'userid' => $USER->id,
|
||||
'context' => context_course::instance($data->course),
|
||||
'courseid' => $data->course,
|
||||
'other' => array('relateduserid' => $data->userid)
|
||||
)
|
||||
);
|
||||
$event->add_record_snapshot('course_completions', $data);
|
||||
$event->trigger();
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
@ -123,6 +123,8 @@ $string['err_noroles'] = 'There are no roles with the capability moodle/course:m
|
||||
$string['err_nousers'] = 'There are no students on this course or group for whom completion information is displayed. (By default, completion information is displayed only for students, so if there are no students, you will see this error. Administrators can alter this option via the admin screens.)';
|
||||
$string['err_settingslocked'] = 'One or more students have already completed a criteria so the settings have been locked. Unlocking the completion criteria settings will delete any existing user data and may cause confusion.';
|
||||
$string['err_system'] = 'An internal error occurred in the completion system. (System administrators can enable debugging information to see more detail.)';
|
||||
$string['eventcoursecompleted'] = 'Course completed';
|
||||
$string['eventcoursemodulecompletionupdated'] = 'Course module completion updated';
|
||||
$string['excelcsvdownload'] = 'Download in Excel-compatible format (.csv)';
|
||||
$string['fraction'] = 'Fraction';
|
||||
$string['graderequired'] = 'Required course grade';
|
||||
|
@ -931,84 +931,6 @@ function badges_add_course_navigation(navigation_node $coursenode, stdClass $cou
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when 'course_completed' event happens.
|
||||
*
|
||||
* @param object $eventdata
|
||||
* @return boolean
|
||||
*/
|
||||
function badges_award_handle_course_criteria_review(stdClass $eventdata) {
|
||||
global $DB, $CFG;
|
||||
|
||||
if (!empty($CFG->enablebadges)) {
|
||||
$userid = $eventdata->userid;
|
||||
$courseid = $eventdata->course;
|
||||
|
||||
// Need to take into account that course can be a part of course_completion and courseset_completion criteria.
|
||||
if ($rs = $DB->get_records('badge_criteria_param', array('name' => 'course_' . $courseid, 'value' => $courseid))) {
|
||||
foreach ($rs as $r) {
|
||||
$crit = $DB->get_record('badge_criteria', array('id' => $r->critid), 'badgeid, criteriatype', MUST_EXIST);
|
||||
$badge = new badge($crit->badgeid);
|
||||
if (!$badge->is_active() || $badge->is_issued($userid)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($badge->criteria[$crit->criteriatype]->review($userid)) {
|
||||
$badge->criteria[$crit->criteriatype]->mark_complete($userid);
|
||||
|
||||
if ($badge->criteria[BADGE_CRITERIA_TYPE_OVERALL]->review($userid)) {
|
||||
$badge->criteria[BADGE_CRITERIA_TYPE_OVERALL]->mark_complete($userid);
|
||||
$badge->issue($userid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when 'activity_completed' event happens.
|
||||
*
|
||||
* @param object $eventdata
|
||||
* @return boolean
|
||||
*/
|
||||
function badges_award_handle_activity_criteria_review(stdClass $eventdata) {
|
||||
global $DB, $CFG;
|
||||
|
||||
if (!empty($CFG->enablebadges)) {
|
||||
$userid = $eventdata->userid;
|
||||
$mod = $eventdata->coursemoduleid;
|
||||
|
||||
if ($eventdata->completionstate == COMPLETION_COMPLETE
|
||||
|| $eventdata->completionstate == COMPLETION_COMPLETE_PASS
|
||||
|| $eventdata->completionstate == COMPLETION_COMPLETE_FAIL) {
|
||||
// Need to take into account that there can be more than one badge with the same activity in its criteria.
|
||||
if ($rs = $DB->get_records('badge_criteria_param', array('name' => 'module_' . $mod, 'value' => $mod))) {
|
||||
foreach ($rs as $r) {
|
||||
$bid = $DB->get_field('badge_criteria', 'badgeid', array('id' => $r->critid), MUST_EXIST);
|
||||
$badge = new badge($bid);
|
||||
if (!$badge->is_active() || $badge->is_issued($userid)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($badge->criteria[BADGE_CRITERIA_TYPE_ACTIVITY]->review($userid)) {
|
||||
$badge->criteria[BADGE_CRITERIA_TYPE_ACTIVITY]->mark_complete($userid);
|
||||
|
||||
if ($badge->criteria[BADGE_CRITERIA_TYPE_OVERALL]->review($userid)) {
|
||||
$badge->criteria[BADGE_CRITERIA_TYPE_OVERALL]->mark_complete($userid);
|
||||
$badge->issue($userid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when 'user_updated' event happens.
|
||||
*
|
||||
|
83
lib/classes/event/course_completed.php
Normal file
83
lib/classes/event/course_completed.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core\event;
|
||||
|
||||
/**
|
||||
* Event when course completed.
|
||||
*
|
||||
* @package core_event
|
||||
* @copyright 2013 Rajesh Taneja <rajesh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class course_completed extends base {
|
||||
|
||||
/**
|
||||
* Initialise required event data properties.
|
||||
*/
|
||||
protected function init() {
|
||||
$this->data['objecttable'] = 'course_completions';
|
||||
$this->data['crud'] = 'u';
|
||||
// TODO: MDL-37658 set level.
|
||||
$this->data['level'] = 50;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns localised event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name() {
|
||||
return new get_string('eventcoursecompleted', 'core_completion');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns non-localised event description with id's for admin use only.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
return 'Course completed by user '.$this->userid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns relevant URL.
|
||||
*
|
||||
* @return \moodle_url
|
||||
*/
|
||||
public function get_url() {
|
||||
return new moodle_url('/report/completion/index.php', array('course' => $this->courseid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return name of the legacy event, which is replaced by this event.
|
||||
*
|
||||
* @return string legacy event name
|
||||
*/
|
||||
public static function get_legacy_eventname() {
|
||||
return 'course_completed';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return course_completed legacy event data.
|
||||
*
|
||||
* @return \stdClass completion data.
|
||||
*/
|
||||
protected function get_legacy_eventdata() {
|
||||
return $this->get_record_snapshot('course_completions', $this->objectid);
|
||||
}
|
||||
|
||||
}
|
83
lib/classes/event/course_module_completion_updated.php
Normal file
83
lib/classes/event/course_module_completion_updated.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core\event;
|
||||
|
||||
/**
|
||||
* Event when course module completion is updated.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2013 Rajesh Taneja <rajesh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class course_module_completion_updated extends base {
|
||||
|
||||
/**
|
||||
* Initialise required event data properties.
|
||||
*/
|
||||
protected function init() {
|
||||
$this->data['objecttable'] = 'course_modules_completion';
|
||||
$this->data['crud'] = 'u';
|
||||
// TODO: MDL-37658 set level.
|
||||
$this->data['level'] = 50;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns localised event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name() {
|
||||
return new get_string('eventcoursemodulecompletionupdated', 'core_completion');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns non-localised event description with id's for admin use only.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
return 'Course module completion updated for user ' . $this->userid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns relevant URL.
|
||||
*
|
||||
* @return \moodle_url
|
||||
*/
|
||||
public function get_url() {
|
||||
return new moodle_url('/report/completion/index.php', array('course' => $this->courseid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return name of the legacy event, which is replaced by this event.
|
||||
*
|
||||
* @return string legacy event name
|
||||
*/
|
||||
public static function get_legacy_eventname() {
|
||||
return 'activity_completion_changed';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return course module completion legacy event data.
|
||||
*
|
||||
* @return \stdClass completion data.
|
||||
*/
|
||||
protected function get_legacy_eventdata() {
|
||||
return $this->get_record_snapshot('course_modules_completion', $this->objectid);
|
||||
}
|
||||
|
||||
}
|
@ -1036,7 +1036,20 @@ class completion_info {
|
||||
}
|
||||
$transaction->allow_commit();
|
||||
|
||||
events_trigger('activity_completion_changed', $data);
|
||||
$cmcontext = context_module::instance($data->coursemoduleid, MUST_EXIST);
|
||||
$coursecontext = $cmcontext->get_parent_context();
|
||||
|
||||
// Trigger an event for course module completion changed.
|
||||
$event = \core\event\course_module_completion_updated::create(
|
||||
array('objectid' => $data->id,
|
||||
'userid' => $USER->id,
|
||||
'context' => $cmcontext,
|
||||
'courseid' => $coursecontext->instanceid,
|
||||
'other' => array('relateduserid' => $data->userid)
|
||||
)
|
||||
);
|
||||
$event->add_record_snapshot('course_modules_completion', $data);
|
||||
$event->trigger();
|
||||
|
||||
if ($data->userid == $USER->id) {
|
||||
$SESSION->completioncache[$cm->course][$cm->id] = $data;
|
||||
|
@ -37,18 +37,6 @@ defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$handlers = array(
|
||||
|
||||
'course_completed' => array (
|
||||
'handlerfile' => '/lib/badgeslib.php',
|
||||
'handlerfunction' => 'badges_award_handle_course_criteria_review',
|
||||
'schedule' => 'instant',
|
||||
'internal' => 1,
|
||||
),
|
||||
'activity_completion_changed' => array (
|
||||
'handlerfile' => '/lib/badgeslib.php',
|
||||
'handlerfunction' => 'badges_award_handle_activity_criteria_review',
|
||||
'schedule' => 'instant',
|
||||
'internal' => 1,
|
||||
),
|
||||
'user_updated' => array (
|
||||
'handlerfile' => '/lib/badgeslib.php',
|
||||
'handlerfunction' => 'badges_award_handle_profile_criteria_review',
|
||||
@ -73,7 +61,18 @@ $handlers = array(
|
||||
/* no more here please, core should not consume any events!!!!!!! */
|
||||
);
|
||||
|
||||
$observers = array(
|
||||
|
||||
array(
|
||||
'eventname' => '\core\event\course_module_completion_updated',
|
||||
'callback' => 'core_badges_observer::course_module_criteria_review',
|
||||
),
|
||||
array(
|
||||
'eventname' => '\core\event\course_completed',
|
||||
'callback' => 'core_badges_observer::course_criteria_review',
|
||||
)
|
||||
|
||||
);
|
||||
|
||||
|
||||
/* List of events thrown from Moodle core
|
||||
|
@ -30,6 +30,11 @@ global $CFG;
|
||||
require_once($CFG->libdir.'/completionlib.php');
|
||||
|
||||
class core_completionlib_testcase extends advanced_testcase {
|
||||
protected $course;
|
||||
protected $user;
|
||||
protected $module1;
|
||||
protected $module2;
|
||||
|
||||
protected function mock_setup() {
|
||||
global $DB, $CFG, $USER;
|
||||
|
||||
@ -40,6 +45,31 @@ class core_completionlib_testcase extends advanced_testcase {
|
||||
$USER = (object)array('id' =>314159);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create course with user and activities.
|
||||
*/
|
||||
protected function setup_data() {
|
||||
global $DB, $CFG;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create a course with activities.
|
||||
$this->course = $this->getDataGenerator()->create_course();
|
||||
$this->user = $this->getDataGenerator()->create_user();
|
||||
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
|
||||
$this->assertNotEmpty($studentrole);
|
||||
|
||||
// Get manual enrolment plugin and enrol user.
|
||||
require_once($CFG->dirroot.'/enrol/manual/locallib.php');
|
||||
$manplugin = enrol_get_plugin('manual');
|
||||
$maninstance = $DB->get_record('enrol', array('courseid' => $this->course->id, 'enrol' => 'manual'), '*', MUST_EXIST);
|
||||
$manplugin->enrol_user($maninstance, $this->user->id, $studentrole->id);
|
||||
$this->assertEquals(1, $DB->count_records('user_enrolments'));
|
||||
|
||||
$this->module1 = $this->getDataGenerator()->create_module('forum', array('course' => $this->course->id));
|
||||
$this->module2 = $this->getDataGenerator()->create_module('forum', array('course' => $this->course->id));
|
||||
}
|
||||
|
||||
public function test_is_enabled() {
|
||||
global $CFG;
|
||||
$this->mock_setup();
|
||||
@ -428,57 +458,55 @@ class core_completionlib_testcase extends advanced_testcase {
|
||||
|
||||
public function test_internal_set_data() {
|
||||
global $DB, $SESSION;
|
||||
$this->mock_setup();
|
||||
$this->setup_data();
|
||||
|
||||
$cm = (object)array('course' => 42, 'id' => 13);
|
||||
$c = new completion_info((object)array('id' => 42));
|
||||
$this->setUser($this->user);
|
||||
$completionauto = array('completion' => COMPLETION_TRACKING_AUTOMATIC);
|
||||
$forum = $this->getDataGenerator()->create_module('forum', array('course' => $this->course->id), $completionauto);
|
||||
$cm = get_coursemodule_from_instance('forum', $forum->id);
|
||||
$c = new completion_info($this->course);
|
||||
|
||||
// 1) Test with new data.
|
||||
$data = (object)array('id'=>0, 'userid' => 314159, 'coursemoduleid' => 99);
|
||||
$DB->expects($this->at(0))
|
||||
->method('start_delegated_transaction')
|
||||
->will($this->returnValue($this->getMock('moodle_transaction', array(), array($DB))));
|
||||
|
||||
$DB->expects($this->at(1))
|
||||
->method('get_field')
|
||||
->with('course_modules_completion', 'id', array('coursemoduleid'=>99, 'userid'=>314159))
|
||||
->will($this->returnValue(false));
|
||||
|
||||
$DB->expects($this->at(2))
|
||||
->method('insert_record')
|
||||
->will($this->returnValue(4));
|
||||
$data = new stdClass();
|
||||
$data->id = 0;
|
||||
$data->userid = $this->user->id;
|
||||
$data->coursemoduleid = $cm->id;
|
||||
$data->completionstate = COMPLETION_COMPLETE;
|
||||
$data->timemodified = time();
|
||||
|
||||
$c->internal_set_data($cm, $data);
|
||||
$this->assertEquals(4, $data->id);
|
||||
$this->assertEquals(array(42 => array(13 => $data)), $SESSION->completioncache);
|
||||
$d1 = $DB->get_field('course_modules_completion', 'id', array('coursemoduleid' => $cm->id));
|
||||
$this->assertEquals($d1, $data->id);
|
||||
$this->assertEquals(array($this->course->id => array($cm->id => $data)), $SESSION->completioncache);
|
||||
|
||||
// 2) Test with existing data and for different user (not cached).
|
||||
unset($SESSION->completioncache);
|
||||
$d2 = (object)array('id' => 7, 'userid' => 17, 'coursemoduleid' => 66);
|
||||
$DB->expects($this->at(0))
|
||||
->method('start_delegated_transaction')
|
||||
->will($this->returnValue($this->getMock('moodle_transaction', array(), array($DB))));
|
||||
$DB->expects($this->at(1))
|
||||
->method('update_record')
|
||||
->with('course_modules_completion', $d2);
|
||||
$c->internal_set_data($cm, $d2);
|
||||
$forum2 = $this->getDataGenerator()->create_module('forum', array('course' => $this->course->id), $completionauto);
|
||||
$cm2 = get_coursemodule_from_instance('forum', $forum2->id);
|
||||
$newuser = $this->getDataGenerator()->create_user();
|
||||
|
||||
$d2 = new stdClass();
|
||||
$d2->id = 7;
|
||||
$d2->userid = $newuser->id;
|
||||
$d2->coursemoduleid = $cm2->id;
|
||||
$d2->completionstate = COMPLETION_COMPLETE;
|
||||
$d2->timemodified = time();
|
||||
$c->internal_set_data($cm2, $d2);
|
||||
$this->assertFalse(isset($SESSION->completioncache));
|
||||
|
||||
// 3) Test where it THINKS the data is new (from cache) but actually
|
||||
// in the database it has been set since.
|
||||
// 1) Test with new data.
|
||||
$data = (object)array('id'=>0, 'userid' => 314159, 'coursemoduleid' => 99);
|
||||
$d3 = (object)array('id' => 13, 'userid' => 314159, 'coursemoduleid' => 99);
|
||||
$DB->expects($this->at(0))
|
||||
->method('start_delegated_transaction')
|
||||
->will($this->returnValue($this->getMock('moodle_transaction', array(), array($DB))));
|
||||
$DB->expects($this->at(1))
|
||||
->method('get_field')
|
||||
->with('course_modules_completion', 'id', array('coursemoduleid' => 99, 'userid' => 314159))
|
||||
->will($this->returnValue(13));
|
||||
$DB->expects($this->at(2))
|
||||
->method('update_record')
|
||||
->with('course_modules_completion', $d3);
|
||||
$forum3 = $this->getDataGenerator()->create_module('forum', array('course' => $this->course->id), $completionauto);
|
||||
$cm3 = get_coursemodule_from_instance('forum', $forum3->id);
|
||||
$newuser2 = $this->getDataGenerator()->create_user();
|
||||
$d3 = new stdClass();
|
||||
$d3->id = 13;
|
||||
$d3->userid = $newuser2->id;
|
||||
$d3->coursemoduleid = $cm3->id;
|
||||
$d3->completionstate = COMPLETION_COMPLETE;
|
||||
$d3->timemodified = time();
|
||||
$DB->insert_record('course_modules_completion', $d3);
|
||||
$c->internal_set_data($cm, $data);
|
||||
}
|
||||
|
||||
@ -719,6 +747,68 @@ class core_completionlib_testcase extends advanced_testcase {
|
||||
$this->assertTrue($c1->has_activities());
|
||||
$this->assertFalse($c2->has_activities());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test course module completion update event.
|
||||
*/
|
||||
public function test_course_module_completion_updated_event() {
|
||||
global $USER;
|
||||
|
||||
$this->setup_data();
|
||||
$this->setAdminUser();
|
||||
|
||||
$completionauto = array('completion' => COMPLETION_TRACKING_AUTOMATIC);
|
||||
$forum = $this->getDataGenerator()->create_module('forum', array('course' => $this->course->id), $completionauto);
|
||||
|
||||
$c = new completion_info($this->course);
|
||||
$activities = $c->get_activities();
|
||||
$this->assertEquals(1, count($activities));
|
||||
$this->assertTrue(isset($activities[$forum->cmid]));
|
||||
$this->assertEquals($activities[$forum->cmid]->name, $forum->name);
|
||||
|
||||
$current = $c->get_data($activities[$forum->cmid], false, $this->user->id);
|
||||
$current->completionstate = COMPLETION_COMPLETE;
|
||||
$current->timemodified = time();
|
||||
$sink = $this->redirectEvents();
|
||||
$c->internal_set_data($activities[$forum->cmid], $current);
|
||||
$events = $sink->get_events();
|
||||
$event = reset($events);
|
||||
$this->assertInstanceOf('\core\event\course_module_completion_updated', $event);
|
||||
$this->assertEquals($forum->cmid, $event->get_record_snapshot('course_modules_completion', $event->objectid)->coursemoduleid);
|
||||
$this->assertEquals($current, $event->get_record_snapshot('course_modules_completion', $event->objectid));
|
||||
$this->assertEquals(context_module::instance($forum->id), $event->get_context());
|
||||
$this->assertEquals($USER->id, $event->userid);
|
||||
$this->assertEquals($this->user->id, $event->other['relateduserid']);
|
||||
$this->assertEventLegacyData($current, $event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test course completed event.
|
||||
*/
|
||||
public function test_course_completed_event() {
|
||||
global $USER;
|
||||
|
||||
$this->setup_data();
|
||||
$this->setAdminUser();
|
||||
|
||||
$completionauto = array('completion' => COMPLETION_TRACKING_AUTOMATIC);
|
||||
$ccompletion = new completion_completion(array('course' => $this->course->id, 'userid' => $this->user->id));
|
||||
|
||||
// Mark course as complete and get triggered event.
|
||||
$sink = $this->redirectEvents();
|
||||
$ccompletion->mark_complete();
|
||||
$events = $sink->get_events();
|
||||
$event = reset($events);
|
||||
|
||||
$this->assertInstanceOf('\core\event\course_completed', $event);
|
||||
$this->assertEquals($this->course->id, $event->get_record_snapshot('course_completions', $event->objectid)->course);
|
||||
$this->assertEquals($this->course->id, $event->courseid);
|
||||
$this->assertEquals($USER->id, $event->userid);
|
||||
$this->assertEquals($this->user->id, $event->other['relateduserid']);
|
||||
$this->assertEquals(context_course::instance($this->course->id), $event->get_context());
|
||||
$data = $ccompletion->get_record_data();
|
||||
$this->assertEventLegacyData($data, $event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user