MDL-39961 Events: Replace Legacy events - User
authorRajesh Taneja <rajesh@moodle.com>
Mon, 19 Aug 2013 09:03:39 +0000 (17:03 +0800)
committerDamyon Wiese <damyon@moodle.com>
Mon, 2 Sep 2013 08:10:05 +0000 (16:10 +0800)
This change includes:
* Added user_updated event, replacing old event
* Added user_created event, replacing old event
* Added user_deleted event, replacing old event
* Added user_loggedout event, replacing old event
* Added user_enrolment_created event, replacing old event
* Added user_enrolment_deleted event, replacing old event
* Added user_enrolment_updated event, replacing old event

38 files changed:
admin/tool/uploaduser/index.php
admin/user.php
auth/db/auth.php
auth/email/auth.php
auth/ldap/auth.php
auth/mnet/auth.php
badges/classes/observer.php
badges/tests/badgeslib_test.php
enrol/manual/locallib.php
enrol/meta/classes/observer.php [new file with mode: 0644]
enrol/meta/db/events.php
enrol/meta/locallib.php
enrol/meta/tests/plugin_test.php
enrol/tests/enrollib_test.php
lang/en/enrol.php
lang/en/moodle.php
lib/badgeslib.php
lib/behat/classes/util.php
lib/classes/event/user_created.php [new file with mode: 0644]
lib/classes/event/user_deleted.php [new file with mode: 0644]
lib/classes/event/user_enrolment_created.php [new file with mode: 0644]
lib/classes/event/user_enrolment_deleted.php [new file with mode: 0644]
lib/classes/event/user_enrolment_updated.php [new file with mode: 0644]
lib/classes/event/user_loggedout.php [new file with mode: 0644]
lib/classes/event/user_updated.php [new file with mode: 0644]
lib/db/events.php
lib/enrollib.php
lib/moodlelib.php
lib/tests/moodlelib_test.php
mod/forum/classes/observer.php [new file with mode: 0644]
mod/forum/db/events.php
mod/forum/lib.php
mod/forum/tests/lib_test.php
user/edit.php
user/editadvanced.php
user/emailupdate.php
user/lib.php
user/tests/userlib_test.php [new file with mode: 0644]

index c052d1c..7949d94 100644 (file)
@@ -27,6 +27,7 @@ require('../../../config.php');
 require_once($CFG->libdir.'/adminlib.php');
 require_once($CFG->libdir.'/csvlib.class.php');
 require_once($CFG->dirroot.'/user/profile/lib.php');
+require_once($CFG->dirroot.'/user/lib.php');
 require_once($CFG->dirroot.'/group/lib.php');
 require_once($CFG->dirroot.'/cohort/lib.php');
 require_once('locallib.php');
@@ -654,9 +655,8 @@ if ($formdata = $mform2->is_cancelled()) {
             }
 
             if ($doupdate or $existinguser->password !== $oldpw) {
-                // we want only users that were really updated
-
-                $DB->update_record('user', $existinguser);
+                // We want only users that were really updated.
+                user_update_user($existinguser, false);
 
                 $upt->track('status', $struserupdated);
                 $usersupdated++;
@@ -668,8 +668,6 @@ if ($formdata = $mform2->is_cancelled()) {
                     profile_save_data($existinguser);
                 }
 
-                events_trigger('user_updated', $existinguser);
-
                 if ($bulk == UU_BULK_UPDATED or $bulk == UU_BULK_ALL) {
                     if (!in_array($user->id, $SESSION->bulk_users)) {
                         $SESSION->bulk_users[] = $user->id;
@@ -789,8 +787,7 @@ if ($formdata = $mform2->is_cancelled()) {
                 $upt->track('password', '-', 'normal', false);
             }
 
-            // create user - insert_record ignores any extra properties
-            $user->id = $DB->insert_record('user', $user);
+            $user->id = user_create_user($user, false);
             $upt->track('username', html_writer::link(new moodle_url('/user/profile.php', array('id'=>$user->id)), s($user->username)), 'normal', false);
 
             // pre-process custom profile menu fields data from csv file
@@ -812,8 +809,6 @@ if ($formdata = $mform2->is_cancelled()) {
             // make sure user context exists
             context_user::instance($user->id);
 
-            events_trigger('user_created', $user);
-
             if ($bulk == UU_BULK_NEW or $bulk == UU_BULK_ALL) {
                 if (!in_array($user->id, $SESSION->bulk_users)) {
                     $SESSION->bulk_users[] = $user->id;
index 0f66603..699babb 100644 (file)
@@ -4,6 +4,7 @@
     require_once($CFG->libdir.'/adminlib.php');
     require_once($CFG->libdir.'/authlib.php');
     require_once($CFG->dirroot.'/user/filters/lib.php');
+    require_once($CFG->dirroot.'/user/lib.php');
 
     $delete       = optional_param('delete', 0, PARAM_INT);
     $confirm      = optional_param('confirm', '', PARAM_ALPHANUM);   //md5 confirmation hash
         if ($user = $DB->get_record('user', array('id'=>$suspend, 'mnethostid'=>$CFG->mnet_localhost_id, 'deleted'=>0))) {
             if (!is_siteadmin($user) and $USER->id != $user->id and $user->suspended != 1) {
                 $user->suspended = 1;
-                $user->timemodified = time();
-                $DB->set_field('user', 'suspended', $user->suspended, array('id'=>$user->id));
-                $DB->set_field('user', 'timemodified', $user->timemodified, array('id'=>$user->id));
-                // force logout
+                // Force logout.
                 session_kill_user($user->id);
-                events_trigger('user_updated', $user);
+                user_update_user($user, false);
             }
         }
         redirect($returnurl);
         if ($user = $DB->get_record('user', array('id'=>$unsuspend, 'mnethostid'=>$CFG->mnet_localhost_id, 'deleted'=>0))) {
             if ($user->suspended != 0) {
                 $user->suspended = 0;
-                $user->timemodified = time();
-                $DB->set_field('user', 'suspended', $user->suspended, array('id'=>$user->id));
-                $DB->set_field('user', 'timemodified', $user->timemodified, array('id'=>$user->id));
-                events_trigger('user_updated', $user);
+                user_update_user($user, false);
             }
         }
         redirect($returnurl);
index de5061d..a01fc6e 100644 (file)
@@ -284,6 +284,7 @@ class auth_plugin_db extends auth_plugin_base {
             $remove_users = $DB->get_records_sql($sql, $params);
 
             if (!empty($remove_users)) {
+                require_once($CFG->dirroot.'/user/lib.php');
                 $trace->output(get_string('auth_dbuserstoremove','auth_db', count($remove_users)));
 
                 foreach ($remove_users as $user) {
@@ -294,8 +295,7 @@ class auth_plugin_db extends auth_plugin_base {
                         $updateuser = new stdClass();
                         $updateuser->id   = $user->id;
                         $updateuser->suspended = 1;
-                        $updateuser->timemodified = time();
-                        $DB->update_record('user', $updateuser);
+                        user_update_user($updateuser, false);
                         $trace->output(get_string('auth_dbsuspenduser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)), 1);
                     }
                 }
index e459004..a670cfc 100644 (file)
@@ -87,17 +87,15 @@ class auth_plugin_email extends auth_plugin_base {
     function user_signup($user, $notify=true) {
         global $CFG, $DB;
         require_once($CFG->dirroot.'/user/profile/lib.php');
+        require_once($CFG->dirroot.'/user/lib.php');
 
         $user->password = hash_internal_user_password($user->password);
 
-        $user->id = $DB->insert_record('user', $user);
+        $user->id = user_create_user($user, false);
 
-        /// Save any custom profile field information
+        // Save any custom profile field information.
         profile_save_data($user);
 
-        $user = $DB->get_record('user', array('id'=>$user->id));
-        events_trigger('user_created', $user);
-
         if (! send_confirmation_email($user)) {
             print_error('auth_emailnoemail','auth_email');
         }
index 866a838..1bad153 100644 (file)
@@ -78,6 +78,7 @@ if (!defined('LDAP_OPT_DIAGNOSTIC_MESSAGE')) {
 
 require_once($CFG->libdir.'/authlib.php');
 require_once($CFG->libdir.'/ldaplib.php');
+require_once($CFG->dirroot.'/user/lib.php');
 
 /**
  * LDAP authentication plugin.
@@ -550,7 +551,7 @@ class auth_plugin_ldap extends auth_plugin_base {
             print_error('auth_ldap_create_error', 'auth_ldap');
         }
 
-        $user->id = $DB->insert_record('user', $user);
+        $user->id = user_create_user($user, false);
 
         // Save any custom profile field information
         profile_save_data($user);
@@ -562,7 +563,6 @@ class auth_plugin_ldap extends auth_plugin_base {
         update_internal_user_password($user, $plainslashedpassword);
 
         $user = $DB->get_record('user', array('id'=>$user->id));
-        events_trigger('user_created', $user);
 
         if (! send_confirmation_email($user)) {
             print_error('noemail', 'auth_ldap');
@@ -612,12 +612,12 @@ class auth_plugin_ldap extends auth_plugin_base {
                 if (!$this->user_activate($username)) {
                     return AUTH_CONFIRM_FAIL;
                 }
-                $DB->set_field('user', 'confirmed', 1, array('id'=>$user->id));
+                $user->confirmed = 1;
                 if ($user->firstaccess == 0) {
-                    $DB->set_field('user', 'firstaccess', time(), array('id'=>$user->id));
+                    $user->firstaccess = time();
                 }
-                $euser = $DB->get_record('user', array('id' => $user->id));
-                events_trigger('user_updated', $euser);
+                require_once($CFG->dirroot.'/user/lib.php');
+                user_update_user($user, false);
                 return AUTH_CONFIRM_OK;
             }
         } else {
@@ -806,10 +806,8 @@ class auth_plugin_ldap extends auth_plugin_base {
                     $updateuser = new stdClass();
                     $updateuser->id = $user->id;
                     $updateuser->suspended = 1;
-                    $DB->update_record('user', $updateuser);
+                    user_update_user($updateuser, false);
                     echo "\t"; print_string('auth_dbsuspenduser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)); echo "\n";
-                    $euser = $DB->get_record('user', array('id' => $user->id));
-                    events_trigger('user_updated', $euser);
                     session_kill_user($user->id);
                 }
             } else {
@@ -835,10 +833,8 @@ class auth_plugin_ldap extends auth_plugin_base {
                     $updateuser->id = $user->id;
                     $updateuser->auth = $this->authtype;
                     $updateuser->suspended = 0;
-                    $DB->update_record('user', $updateuser);
+                    user_update_user($updateuser, false);
                     echo "\t"; print_string('auth_dbreviveduser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)); echo "\n";
-                    $euser = $DB->get_record('user', array('id' => $user->id));
-                    events_trigger('user_updated', $euser);
                 }
             } else {
                 print_string('nouserentriestorevive', 'auth_ldap');
@@ -950,10 +946,10 @@ class auth_plugin_ldap extends auth_plugin_base {
                     $user->lang = $CFG->lang;
                 }
 
-                $id = $DB->insert_record('user', $user);
+                $id = user_create_user($user, false);
                 echo "\t"; print_string('auth_dbinsertuser', 'auth_db', array('name'=>$user->username, 'id'=>$id)); echo "\n";
                 $euser = $DB->get_record('user', array('id' => $id));
-                events_trigger('user_created', $euser);
+
                 if (!empty($this->config->forcechangepassword)) {
                     set_user_preference('auth_forcepasswordchange', 1, $id);
                 }
@@ -1011,22 +1007,25 @@ class auth_plugin_ldap extends auth_plugin_base {
                 $updatekeys = array_keys($newinfo);
             }
 
-            foreach ($updatekeys as $key) {
-                if (isset($newinfo[$key])) {
-                    $value = $newinfo[$key];
-                } else {
-                    $value = '';
-                }
+            if (!empty($updatekeys)) {
+                $newuser = new stdClass();
+                $newuser->id = $userid;
+
+                foreach ($updatekeys as $key) {
+                    if (isset($newinfo[$key])) {
+                        $value = $newinfo[$key];
+                    } else {
+                        $value = '';
+                    }
 
-                if (!empty($this->config->{'field_updatelocal_' . $key})) {
-                    if ($user->{$key} != $value) { // only update if it's changed
-                        $DB->set_field('user', $key, $value, array('id'=>$userid));
+                    if (!empty($this->config->{'field_updatelocal_' . $key})) {
+                        // Only update if it's changed.
+                        if ($user->{$key} != $value) {
+                            $newuser->$key = $value;
+                        }
                     }
                 }
-            }
-            if (!empty($updatekeys)) {
-                $euser = $DB->get_record('user', array('id' => $userid));
-                events_trigger('user_updated', $euser);
+                user_update_user($newuser, false);
             }
         } else {
             return false;
index c1861fa..2f626bd 100644 (file)
@@ -216,6 +216,7 @@ class auth_plugin_mnet extends auth_plugin_base {
         global $CFG, $DB;
         require_once $CFG->dirroot . '/mnet/xmlrpc/client.php';
         require_once $CFG->libdir . '/gdlib.php';
+        require_once($CFG->dirroot.'/user/lib.php');
 
         // verify the remote host is configured locally before attempting RPC call
         if (! $remotehost = $DB->get_record('mnet_host', array('wwwroot' => $remotepeer->wwwroot, 'deleted' => 0))) {
@@ -361,8 +362,7 @@ class auth_plugin_mnet extends auth_plugin_base {
         if (empty($localuser->firstaccess)) { // Now firstaccess, grab it here
             $localuser->firstaccess = time();
         }
-
-        $DB->update_record('user', $localuser);
+        user_update_user($localuser, false);
 
         if (!$firsttime) {
             // repeat customer! let the IDP know about enrolments
index 6d7b054..39c2c4c 100644 (file)
@@ -72,7 +72,7 @@ class core_badges_observer {
     /**
      * Triggered when 'course_completed' event is triggered.
      *
-     * @param   \core\event\course_completed $event
+     * @param \core\event\course_completed $event
      */
     public static function course_criteria_review(\core\event\course_completed $event) {
         global $DB, $CFG;
@@ -105,4 +105,36 @@ class core_badges_observer {
             }
         }
     }
+
+    /**
+     * Triggered when 'user_updated' event happens.
+     *
+     * @param \core\event\user_updated $event event generated when user profile is updated.
+     */
+    public static function profile_criteria_review(\core\event\user_updated $event) {
+        global $DB, $CFG;
+
+        if (!empty($CFG->enablebadges)) {
+            require_once($CFG->dirroot.'/lib/badgeslib.php');
+            $userid = $event->objectid;
+
+            if ($rs = $DB->get_records('badge_criteria', array('criteriatype' => BADGE_CRITERIA_TYPE_PROFILE))) {
+                foreach ($rs as $r) {
+                    $badge = new badge($r->badgeid);
+                    if (!$badge->is_active() || $badge->is_issued($userid)) {
+                        continue;
+                    }
+
+                    if ($badge->criteria[BADGE_CRITERIA_TYPE_PROFILE]->review($userid)) {
+                        $badge->criteria[BADGE_CRITERIA_TYPE_PROFILE]->mark_complete($userid);
+
+                        if ($badge->criteria[BADGE_CRITERIA_TYPE_OVERALL]->review($userid)) {
+                            $badge->criteria[BADGE_CRITERIA_TYPE_OVERALL]->mark_complete($userid);
+                            $badge->issue($userid);
+                        }
+                    }
+                }
+            }
+        }
+    }
 }
index fa7b7cb..a3b2878 100644 (file)
@@ -260,4 +260,23 @@ class core_badgeslib_testcase extends advanced_testcase {
         $this->assertDebuggingCalled('Error baking badge image!');
         $this->assertTrue($badge->is_issued($this->user->id));
     }
+
+    /**
+     * Test badges observer when user_updated event is fired.
+     */
+    public function test_badges_observer_profile_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_PROFILE, 'badgeid' => $badge->id));
+        $criteria_overall1->save(array('agg' => BADGE_CRITERIA_AGGREGATION_ALL, 'field_address' => 'address'));
+
+        $this->user->address = 'Test address';
+        user_update_user($this->user, false);
+        // Check if badge is awarded.
+        $this->assertDebuggingCalled('Error baking badge image!');
+        $this->assertTrue($badge->is_issued($this->user->id));
+    }
 }
index 5c3e345..a4f7a00 100644 (file)
@@ -257,7 +257,17 @@ class enrol_manual_editselectedusers_operation extends enrol_bulk_enrolment_oper
                 foreach ($user->enrolments as $enrolment) {
                     $enrolment->courseid  = $enrolment->enrolmentinstance->courseid;
                     $enrolment->enrol     = 'manual';
-                    events_trigger('user_enrol_modified', $enrolment);
+                    // Trigger event.
+                    $event = \core\event\user_enrolment_updated::create(
+                            array(
+                                'objectid' => $enrolment->id,
+                                'courseid' => $enrolment->courseid,
+                                'context' => context_course::instance($enrolment->courseid),
+                                'relateduserid' => $user->id,
+                                'other' => array('enrol' => 'manual')
+                                )
+                            );
+                    $event->trigger();
                 }
             }
             return true;
diff --git a/enrol/meta/classes/observer.php b/enrol/meta/classes/observer.php
new file mode 100644 (file)
index 0000000..625d232
--- /dev/null
@@ -0,0 +1,102 @@
+<?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/>.
+
+/**
+ * Event observer for meta enrolment plugin.
+ *
+ * @package    enrol_meta
+ * @copyright  2013 Rajesh Taneja <rajesh@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->dirroot.'/enrol/meta/locallib.php');
+
+/**
+ * Event observer for enrol_meta.
+ *
+ * @package    enrol_meta
+ * @copyright  2013 Rajesh Taneja <rajesh@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class enrol_meta_observer extends enrol_meta_handler {
+
+    /**
+     * Triggered via user_enrolment_created event.
+     *
+     * @param \core\event\user_enrolment_created $event
+     * @return bool true on success.
+     */
+    public static function user_enrolment_created(\core\event\user_enrolment_created $event) {
+        if (!enrol_is_enabled('meta')) {
+            // No more enrolments for disabled plugins.
+            return true;
+        }
+
+        if ($event->other['enrol'] === 'meta') {
+            // Prevent circular dependencies - we can not sync meta enrolments recursively.
+            return true;
+        }
+
+        self::sync_course_instances($event->courseid, $event->relateduserid);
+        return true;
+    }
+
+    /**
+     * Triggered via user_enrolment_deleted event.
+     *
+     * @param \core\event\user_enrolment_deleted $event
+     * @return bool true on success.
+     */
+    public static function user_enrolment_deleted(\core\event\user_enrolment_deleted $event) {
+        if (!enrol_is_enabled('meta')) {
+            // This is slow, let enrol_meta_sync() deal with disabled plugin.
+            return true;
+        }
+
+        if ($event->other['enrol'] === 'meta') {
+            // Prevent circular dependencies - we can not sync meta enrolments recursively.
+            return true;
+        }
+
+        self::sync_course_instances($event->courseid, $event->relateduserid);
+
+        return true;
+    }
+
+    /**
+     * Triggered via user_enrolment_updated event.
+     *
+     * @param \core\event\user_enrolment_updated $event
+     * @return bool true on success
+     */
+    public static function user_enrolment_updated(\core\event\user_enrolment_updated $event) {
+        if (!enrol_is_enabled('meta')) {
+            // No modifications if plugin disabled.
+            return true;
+        }
+
+        if ($event->other['enrol'] === 'meta') {
+            // Prevent circular dependencies - we can not sync meta enrolments recursively.
+            return true;
+        }
+
+        self::sync_course_instances($event->courseid, $event->relateduserid);
+
+        return true;
+    }
+}
index c1a2d70..08c9625 100644 (file)
@@ -41,31 +41,27 @@ $handlers = array (
         'internal'         => 1,
     ),
 
-    'user_enrolled' => array (
+    'course_deleted' => array (
         'handlerfile'      => '/enrol/meta/locallib.php',
-        'handlerfunction'  => array('enrol_meta_handler', 'user_enrolled'),
+        'handlerfunction'  => array('enrol_meta_handler', 'course_deleted'),
         'schedule'         => 'instant',
         'internal'         => 1,
     ),
+);
 
-    'user_unenrolled' => array (
-        'handlerfile'      => '/enrol/meta/locallib.php',
-        'handlerfunction'  => array('enrol_meta_handler', 'user_unenrolled'),
-        'schedule'         => 'instant',
-        'internal'         => 1,
-    ),
+// List of observers.
+$observers = array(
 
-    'user_enrol_modified' => array (
-        'handlerfile'      => '/enrol/meta/locallib.php',
-        'handlerfunction'  => array('enrol_meta_handler', 'user_enrol_modified'),
-        'schedule'         => 'instant',
-        'internal'         => 1,
+    array(
+        'eventname'   => '\core\event\user_enrolment_created',
+        'callback'    => 'enrol_meta_observer::user_enrolment_created',
     ),
-
-    'course_deleted' => array (
-        'handlerfile'      => '/enrol/meta/locallib.php',
-        'handlerfunction'  => array('enrol_meta_handler', 'course_deleted'),
-        'schedule'         => 'instant',
-        'internal'         => 1,
+    array(
+        'eventname'   => '\core\event\user_enrolment_deleted',
+        'callback'    => 'enrol_meta_observer::user_enrolment_deleted',
+    ),
+    array(
+        'eventname'   => '\core\event\user_enrolment_updated',
+        'callback'    => 'enrol_meta_observer::user_enrolment_updated',
     ),
 );
index 3a3c26b..c20bfaf 100644 (file)
@@ -293,72 +293,6 @@ class enrol_meta_handler {
         return true;
     }
 
-    /**
-     * Triggered via user enrolled event.
-     * @static
-     * @param stdClass $ue
-     * @return bool success
-     */
-    public static function user_enrolled($ue) {
-        if (!enrol_is_enabled('meta')) {
-            // no more enrolments for disabled plugins
-            return true;
-        }
-
-        if ($ue->enrol === 'meta') {
-            // prevent circular dependencies - we can not sync meta enrolments recursively
-            return true;
-        }
-
-        self::sync_course_instances($ue->courseid, $ue->userid);
-
-        return true;
-    }
-
-    /**
-     * Triggered via user unenrolled event.
-     * @static
-     * @param stdClass $ue
-     * @return bool success
-     */
-    public static function user_unenrolled($ue) {
-        if (!enrol_is_enabled('meta')) {
-            // This is slow, let enrol_meta_sync() deal with disabled plugin.
-            return true;
-        }
-
-        if ($ue->enrol === 'meta') {
-            // prevent circular dependencies - we can not sync meta enrolments recursively
-            return true;
-        }
-
-        self::sync_course_instances($ue->courseid, $ue->userid);
-
-        return true;
-    }
-
-    /**
-     * Triggered via user enrolment modification  event.
-     * @static
-     * @param stdClass $ue
-     * @return bool success
-     */
-    public static function user_enrol_modified($ue) {
-        if (!enrol_is_enabled('meta')) {
-            // no modifications if plugin disabled
-            return true;
-        }
-
-        if ($ue->enrol === 'meta') {
-            // prevent circular dependencies - we can not sync meta enrolments recursively
-            return true;
-        }
-
-        self::sync_course_instances($ue->courseid, $ue->userid);
-
-        return true;
-    }
-
     /**
      * Triggered via course_deleted event.
      * @static
index fdfec33..05cb522 100644 (file)
@@ -439,4 +439,112 @@ class enrol_meta_plugin_testcase extends advanced_testcase {
         delete_course($course4, false);
 
     }
+
+    /**
+     * Test user_enrolment_created event.
+     */
+    public function test_user_enrolment_created_observer() {
+        global $DB;
+
+        $this->resetAfterTest();
+
+        $metaplugin = enrol_get_plugin('meta');
+        $user1 = $this->getDataGenerator()->create_user();
+        $course1 = $this->getDataGenerator()->create_course();
+        $course2 = $this->getDataGenerator()->create_course();
+        $student = $DB->get_record('role', array('shortname' => 'student'));
+
+        $e1 = $metaplugin->add_instance($course2, array('customint1' => $course1->id));
+        $enrol1 = $DB->get_record('enrol', array('id' => $e1));
+
+        // Enrol user and capture event.
+        $sink = $this->redirectEvents();
+
+        $metaplugin->enrol_user($enrol1, $user1->id, $student->id);
+        $events = $sink->get_events();
+        $sink->close();
+        $event = array_shift($events);
+
+        // Test Event.
+        $dbuserenrolled = $DB->get_record('user_enrolments', array('userid' => $user1->id));
+        $this->assertInstanceOf('\core\event\user_enrolment_created', $event);
+        $this->assertEquals($dbuserenrolled->id, $event->objectid);
+        $this->assertEquals('user_enrolled', $event->get_legacy_eventname());
+        $expectedlegacyeventdata = $dbuserenrolled;
+        $expectedlegacyeventdata->enrol = 'meta';
+        $expectedlegacyeventdata->courseid = $course2->id;
+        $this->assertEventLegacyData($expectedlegacyeventdata, $event);
+    }
+
+    /**
+     * Test user_enrolment_deleted observer.
+     */
+    public function test_user_enrolment_deleted_observer() {
+        global $DB;
+
+        $this->resetAfterTest(true);
+
+        $metalplugin = enrol_get_plugin('meta');
+        $user1 = $this->getDataGenerator()->create_user();
+        $course1 = $this->getDataGenerator()->create_course();
+        $course2 = $this->getDataGenerator()->create_course();
+        $student = $DB->get_record('role', array('shortname'=>'student'));
+
+        $e1 = $metalplugin->add_instance($course2, array('customint1' => $course1->id));
+        $enrol1 = $DB->get_record('enrol', array('id' => $e1));
+
+        // Enrol user.
+        $metalplugin->enrol_user($enrol1, $user1->id, $student->id);
+        $this->assertEquals(1, $DB->count_records('user_enrolments'));
+
+        // Unenrol user and capture event.
+        $sink = $this->redirectEvents();
+        $metalplugin->unenrol_user($enrol1, $user1->id);
+        $events = $sink->get_events();
+        $sink->close();
+        $event = array_pop($events);
+
+        $this->assertEquals(0, $DB->count_records('user_enrolments'));
+        $this->assertInstanceOf('\core\event\user_enrolment_deleted', $event);
+        $this->assertEquals('user_unenrolled', $event->get_legacy_eventname());
+    }
+
+    /**
+     * Test user_enrolment_updated event.
+     */
+    public function test_user_enrolment_updated_observer() {
+        global $DB;
+
+        $this->resetAfterTest(true);
+
+        $metalplugin = enrol_get_plugin('meta');
+        $user1 = $this->getDataGenerator()->create_user();
+        $course1 = $this->getDataGenerator()->create_course();
+        $course2 = $this->getDataGenerator()->create_course();
+        $student = $DB->get_record('role', array('shortname'=>'student'));
+
+        $e1 = $metalplugin->add_instance($course2, array('customint1' => $course1->id));
+        $enrol1 = $DB->get_record('enrol', array('id' => $e1));
+
+        // Enrol user.
+        $metalplugin->enrol_user($enrol1, $user1->id, $student->id);
+        $this->assertEquals(1, $DB->count_records('user_enrolments'));
+
+        // Updated enrolment for user and capture event.
+        $sink = $this->redirectEvents();
+        $metalplugin->update_user_enrol($enrol1, $user1->id, ENROL_USER_SUSPENDED, null, time());
+        $events = $sink->get_events();
+        $sink->close();
+        $event = array_shift($events);
+
+        // Test Event.
+        $dbuserenrolled = $DB->get_record('user_enrolments', array('userid' => $user1->id));
+        $this->assertInstanceOf('\core\event\user_enrolment_updated', $event);
+        $this->assertEquals($dbuserenrolled->id, $event->objectid);
+        $this->assertEquals('user_enrol_modified', $event->get_legacy_eventname());
+        $expectedlegacyeventdata = $dbuserenrolled;
+        $expectedlegacyeventdata->enrol = 'meta';
+        $expectedlegacyeventdata->courseid = $course2->id;
+        $this->assertEventLegacyData($expectedlegacyeventdata, $event);
+    }
 }
index cba40a8..bbdc3bc 100644 (file)
@@ -279,4 +279,41 @@ class core_enrollib_testcase extends advanced_testcase {
         // It should be course 1.
         $this->assertEquals($sharedcourse->id, $course1->id);
     }
+
+    /**
+     * Test user enrolment created event.
+     */
+    public function test_user_enrolment_created_event() {
+        global $DB;
+
+        $this->resetAfterTest();
+
+        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
+        $this->assertNotEmpty($studentrole);
+
+        $admin = get_admin();
+
+        $course1 = $this->getDataGenerator()->create_course();
+
+        $maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
+
+        $manual = enrol_get_plugin('manual');
+        $this->assertNotEmpty($manual);
+
+        // Enrol user and capture event.
+        $sink = $this->redirectEvents();
+        $manual->enrol_user($maninstance1, $admin->id, $studentrole->id);
+        $events = $sink->get_events();
+        $sink->close();
+        $event = array_shift($events);
+
+        $dbuserenrolled = $DB->get_record('user_enrolments', array('userid' => $admin->id));
+        $this->assertInstanceOf('\core\event\user_enrolment_created', $event);
+        $this->assertEquals($dbuserenrolled->id, $event->objectid);
+        $this->assertEquals('user_enrolled', $event->get_legacy_eventname());
+        $expectedlegacyeventdata = $dbuserenrolled;
+        $expectedlegacyeventdata->enrol = $manual->get_name();
+        $expectedlegacyeventdata->courseid = $course1->id;
+        $this->assertEventLegacyData($expectedlegacyeventdata, $event);
+    }
 }
index 2beaab1..50c6573 100644 (file)
@@ -69,6 +69,9 @@ $string['errorenrolcohort'] = 'Error creating cohort sync enrolment instance in
 $string['errorenrolcohortusers'] = 'Error enrolling cohort members in this course.';
 $string['errorthresholdlow'] = 'Notification threshold must be at least 1 day.';
 $string['errorwithbulkoperation'] = 'There was an error while processing your bulk enrolment change.';
+$string['eventuserenrolmentcreated'] = 'User enrolled in course';
+$string['eventuserenrolmentdeleted'] = 'User unenrolled from course';
+$string['eventuserenrolmentupdated'] = 'User unenrolment updated';
 $string['expirynotify'] = 'Notify before enrolment expires';
 $string['expirynotify_help'] = 'This setting determines whether enrolment expiry notification messages are sent.';
 $string['expirynotifyall'] = 'Enroller and enrolled user';
index 10c69f5..ac711e3 100644 (file)
@@ -667,6 +667,10 @@ $string['eventcoursedeleted'] = 'Course deleted';
 $string['eventcourserestored'] = 'Course restored';
 $string['eventcourseupdated'] = 'Course updated';
 $string['eventcoursesectionupdated'] = ' Course section updated';
+$string['eventusercreated'] = 'User created';
+$string['eventuserdeleted'] = 'User deleted';
+$string['eventuserloggedout'] = 'User logged out';
+$string['eventuserupdated'] = 'User updated';
 $string['everybody'] = 'Everybody';
 $string['executeat'] = 'Execute at';
 $string['existing'] = 'Existing';
index 4a4b3fb..061ecd3 100644 (file)
@@ -931,40 +931,6 @@ function badges_add_course_navigation(navigation_node $coursenode, stdClass $cou
     }
 }
 
-/**
- * Triggered when 'user_updated' event happens.
- *
- * @param   object $eventdata Holds all information about a user.
- * @return  boolean
- */
-function badges_award_handle_profile_criteria_review(stdClass $eventdata) {
-    global $DB, $CFG;
-
-    if (!empty($CFG->enablebadges)) {
-        $userid = $eventdata->id;
-
-        if ($rs = $DB->get_records('badge_criteria', array('criteriatype' => BADGE_CRITERIA_TYPE_PROFILE))) {
-            foreach ($rs as $r) {
-                $badge = new badge($r->badgeid);
-                if (!$badge->is_active() || $badge->is_issued($userid)) {
-                    continue;
-                }
-
-                if ($badge->criteria[BADGE_CRITERIA_TYPE_PROFILE]->review($userid)) {
-                    $badge->criteria[BADGE_CRITERIA_TYPE_PROFILE]->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 badge is manually awarded.
  *
index 2ac98dd..64727eb 100644 (file)
@@ -58,8 +58,8 @@ class behat_util extends testing_util {
      * @return void
      */
     public static function install_site() {
-        global $DB;
-
+        global $DB, $CFG;
+        require_once($CFG->dirroot.'/user/lib.php');
         if (!defined('BEHAT_UTIL')) {
             throw new coding_exception('This method can be only used by Behat CLI tool');
         }
@@ -82,7 +82,7 @@ class behat_util extends testing_util {
         $user->lastname = 'User';
         $user->city = 'Perth';
         $user->country = 'AU';
-        $DB->update_record('user', $user);
+        user_update_user($user, false);
 
         // Disable email message processor.
         $DB->set_field('message_processors', 'enabled', '0', array('name' => 'email'));
diff --git a/lib/classes/event/user_created.php b/lib/classes/event/user_created.php
new file mode 100644 (file)
index 0000000..892efd5
--- /dev/null
@@ -0,0 +1,99 @@
+<?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/>.
+
+/**
+ * User created event.
+ *
+ * @package    core
+ * @copyright  2013 Rajesh Taneja <rajesh@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace core\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Event when new user profile is created.
+ *
+ * @package    core
+ * @copyright  2013 Rajesh Taneja <rajesh@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class user_created extends base {
+
+    /**
+     * Initialise required event data properties.
+     */
+    protected function init() {
+        $this->data['objecttable'] = 'user';
+        $this->data['crud'] = 'c';
+        $this->data['level'] = self::LEVEL_OTHER;
+    }
+
+    /**
+     * Returns localised event name.
+     *
+     * @return string
+     */
+    public static function get_name() {
+        return get_string('eventusercreated');
+    }
+
+    /**
+     * Returns non-localised event description with id's for admin use only.
+     *
+     * @return string
+     */
+    public function get_description() {
+        return 'Profile created for user '.$this->objectid;
+    }
+
+    /**
+     * Returns relevant URL.
+     *
+     * @return \moodle_url
+     */
+    public function get_url() {
+        return new \moodle_url('/user/view.php', array('id' => $this->objectid));
+    }
+
+    /**
+     * Return name of the legacy event, which is replaced by this event.
+     *
+     * @return string legacy event name
+     */
+    public static function get_legacy_eventname() {
+        return 'user_created';
+    }
+
+    /**
+     * Return user_created legacy event data.
+     *
+     * @return \stdClass user data.
+     */
+    protected function get_legacy_eventdata() {
+        return $this->get_record_snapshot('user', $this->objectid);
+    }
+
+    /**
+     * Returns array of parameters to be passed to legacy add_to_log() function.
+     *
+     * @return array
+     */
+    protected function get_legacy_logdata() {
+        return array(SITEID, 'user', 'add', '/view.php?id='.$this->objectid, fullname($this->get_legacy_eventdata()));
+    }
+}
diff --git a/lib/classes/event/user_deleted.php b/lib/classes/event/user_deleted.php
new file mode 100644 (file)
index 0000000..545d691
--- /dev/null
@@ -0,0 +1,105 @@
+<?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/>.
+
+/**
+ * User deleted event.
+ *
+ * @package    core
+ * @copyright  2013 Rajesh Taneja <rajesh@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace core\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Event when user profile is deleted.
+ *
+ * @package    core
+ * @copyright  2013 Rajesh Taneja <rajesh@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class user_deleted extends base {
+
+    /**
+     * Initialise required event data properties.
+     */
+    protected function init() {
+        $this->data['objecttable'] = 'user';
+        $this->data['crud'] = 'd';
+        $this->data['level'] = self::LEVEL_OTHER;
+    }
+
+    /**
+     * Returns localised event name.
+     *
+     * @return string
+     */
+    public static function get_name() {
+        return get_string('eventuserdeleted');
+    }
+
+    /**
+     * Returns non-localised event description with id's for admin use only.
+     *
+     * @return string
+     */
+    public function get_description() {
+        $user = (object)$this->other['user'];
+        return 'User profile deleted for user '.$user->firstname.' '.$user->lastname.' id ('.$user->id.')';
+    }
+
+    /**
+     * Return name of the legacy event, which is replaced by this event.
+     *
+     * @return string legacy event name
+     */
+    public static function get_legacy_eventname() {
+        return 'user_deleted';
+    }
+
+    /**
+     * Return user_deleted legacy event data.
+     *
+     * @return \stdClass user data.
+     */
+    protected function get_legacy_eventdata() {
+        return (object)$this->other['user'];
+    }
+
+    /**
+     * Returns array of parameters to be passed to legacy add_to_log() function.
+     *
+     * @return array
+     */
+    protected function get_legacy_logdata() {
+        $user = (object)$this->other['user'];
+        return array(SITEID, 'user', 'delete', "view.php?id=$user->id", $user->firstname.' '.$user->lastname);
+    }
+
+    /**
+     * Custom validation.
+     *
+     * @throws \coding_exception
+     * @return void
+     */
+    protected function validate_data() {
+        parent::validate_data();
+        if (!isset($this->other['user'])) {
+            throw new \coding_exception('user must be set in $other.');
+        }
+    }
+}
diff --git a/lib/classes/event/user_enrolment_created.php b/lib/classes/event/user_enrolment_created.php
new file mode 100644 (file)
index 0000000..d45ca6d
--- /dev/null
@@ -0,0 +1,109 @@
+<?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/>.
+
+/**
+ * User enrolment created event.
+ *
+ * @package    core
+ * @copyright  2013 Rajesh Taneja <rajesh@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace core\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Event when user is enrolled in a course.
+ *
+ * @package    core
+ * @copyright  2013 Rajesh Taneja <rajesh@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class user_enrolment_created extends base {
+
+    /**
+     * Initialise required event data properties.
+     */
+    protected function init() {
+        $this->data['objecttable'] = 'user_enrolments';
+        $this->data['crud'] = 'c';
+        $this->data['level'] = self::LEVEL_TEACHING;
+    }
+
+    /**
+     * Returns localised event name.
+     *
+     * @return string
+     */
+    public static function get_name() {
+        return get_string('eventuserenrolmentcreated', 'core_enrol');
+    }
+
+    /**
+     * Returns non-localised event description with id's for admin use only.
+     *
+     * @return string
+     */
+    public function get_description() {
+        return 'User '.$this->relateduserid. ' is enrolled in course '.$this->courseid.' by user '.$this->userid;
+    }
+
+    /**
+     * Returns relevant URL.
+     *
+     * @return \moodle_url
+     */
+    public function get_url() {
+        return new \moodle_url('/enrol/users.php', array('id' => $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 'user_enrolled';
+    }
+
+    /**
+     * Return user_enrolled legacy event data.
+     *
+     * @return \stdClass
+     */
+    protected function get_legacy_eventdata() {
+        $legacyeventdata = $this->get_record_snapshot('user_enrolments', $this->objectid);
+        $legacyeventdata->enrol = $this->other['enrol'];
+        $legacyeventdata->courseid = $this->courseid;
+        return $legacyeventdata;
+    }
+
+    /**
+     * Custom validation.
+     *
+     * @throws \coding_exception
+     * @return void
+     */
+    protected function validate_data() {
+        parent::validate_data();
+        if (!isset($this->other['enrol'])) {
+            throw new \coding_exception('Enrolment plugin name must be set in $other.');
+        }
+        if (!isset($this->relateduserid)) {
+            throw new \coding_exception('Related user id must be set.');
+        }
+    }
+}
diff --git a/lib/classes/event/user_enrolment_deleted.php b/lib/classes/event/user_enrolment_deleted.php
new file mode 100644 (file)
index 0000000..82e523f
--- /dev/null
@@ -0,0 +1,110 @@
+<?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/>.
+
+/**
+ * User enrolment deleted event.
+ *
+ * @package    core
+ * @copyright  2013 Rajesh Taneja <rajesh@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace core\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Event when user is unenrolled from a course.
+ *
+ * @package    core
+ * @copyright  2013 Rajesh Taneja <rajesh@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class user_enrolment_deleted extends base {
+
+    /**
+     * Initialise required event data properties.
+     */
+    protected function init() {
+        $this->data['objecttable'] = 'user_enrolments';
+        $this->data['crud'] = 'd';
+        $this->data['level'] = self::LEVEL_TEACHING;
+    }
+
+    /**
+     * Returns localised event name.
+     *
+     * @return string
+     */
+    public static function get_name() {
+        return get_string('eventuserenrolmentdeleted', 'core_enrol');
+    }
+
+    /**
+     * Returns non-localised event description with id's for admin use only.
+     *
+     * @return string
+     */
+    public function get_description() {
+        return 'User '.$this->relateduserid. ' is enrolled in course '.$this->courseid.' by user '.$this->userid;
+    }
+
+    /**
+     * Returns relevant URL.
+     *
+     * @return \moodle_url
+     */
+    public function get_url() {
+        return new \moodle_url('/enrol/users.php', array('id' => $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 'user_unenrolled';
+    }
+
+    /**
+     * Return user_unenrolled legacy event data.
+     *
+     * @return \stdClass
+     */
+    protected function get_legacy_eventdata() {
+        return (object)$this->other['userenrolment'];
+    }
+
+
+    /**
+     * Custom validation.
+     *
+     * @throws \coding_exception
+     * @return void
+     */
+    protected function validate_data() {
+        parent::validate_data();
+        if (!isset($this->other['userenrolment'])) {
+            throw new \coding_exception('User enrolment must be set in $other.');
+        }
+        if (!isset($this->other['enrol'])) {
+            throw new \coding_exception('Enrolment plugin name must be set in $other.');
+        }
+        if (!isset($this->relateduserid)) {
+            throw new \coding_exception('Related user id must be set.');
+        }
+    }
+}
diff --git a/lib/classes/event/user_enrolment_updated.php b/lib/classes/event/user_enrolment_updated.php
new file mode 100644 (file)
index 0000000..786f519
--- /dev/null
@@ -0,0 +1,109 @@
+<?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/>.
+
+/**
+ * User enrolment updated event.
+ *
+ * @package    core
+ * @copyright  2013 Rajesh Taneja <rajesh@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace core\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Event when user enrolment 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 user_enrolment_updated extends base {
+
+    /**
+     * Initialise required event data properties.
+     */
+    protected function init() {
+        $this->data['objecttable'] = 'user_enrolments';
+        $this->data['crud'] = 'u';
+        $this->data['level'] = self::LEVEL_TEACHING;
+    }
+
+    /**
+     * Returns localised event name.
+     *
+     * @return string
+     */
+    public static function get_name() {
+        return get_string('eventuserenrolmentupdated', 'core_enrol');
+    }
+
+    /**
+     * Returns non-localised event description with id's for admin use only.
+     *
+     * @return string
+     */
+    public function get_description() {
+        return 'User '.$this->relateduserid. ' has updated enrolment for user '.$this->userid.' in course '.$this->courseid;
+    }
+
+    /**
+     * Returns relevant URL.
+     *
+     * @return \moodle_url
+     */
+    public function get_url() {
+        return new \moodle_url('/enrol/users.php', array('id' => $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 'user_enrol_modified';
+    }
+
+    /**
+     * Return user_enrol_modified legacy event data.
+     *
+     * @return \stdClass
+     */
+    protected function get_legacy_eventdata() {
+        $legacyeventdata = $this->get_record_snapshot('user_enrolments', $this->objectid);
+        $legacyeventdata->enrol = $this->other['enrol'];
+        $legacyeventdata->courseid = $this->courseid;
+        return $legacyeventdata;
+    }
+
+    /**
+     * Custom validation.
+     *
+     * @throws \coding_exception
+     * @return void
+     */
+    protected function validate_data() {
+        parent::validate_data();
+        if (!isset($this->other['enrol'])) {
+            throw new \coding_exception('Enrolment plugin name must be set in $other.');
+        }
+        if (!isset($this->relateduserid)) {
+            throw new \coding_exception('Related user id must be set.');
+        }
+    }
+}
diff --git a/lib/classes/event/user_loggedout.php b/lib/classes/event/user_loggedout.php
new file mode 100644 (file)
index 0000000..f881b47
--- /dev/null
@@ -0,0 +1,100 @@
+<?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/>.
+
+/**
+ * User logout event.
+ *
+ * @package    core
+ * @copyright  2013 Rajesh Taneja <rajesh@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace core\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Event when user logout.
+ *
+ * @package    core
+ * @copyright  2013 Rajesh Taneja <rajesh@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class user_loggedout extends base {
+
+    /**
+     * Initialise required event data properties.
+     */
+    protected function init() {
+        $this->data['objecttable'] = 'user';
+        $this->data['crud'] = 'r';
+        $this->data['level'] = self::LEVEL_OTHER;
+    }
+
+    /**
+     * Returns localised event name.
+     *
+     * @return string
+     */
+    public static function get_name() {
+        return get_string('eventuserloggedout');
+    }
+
+    /**
+     * Returns non-localised event description with id's for admin use only.
+     *
+     * @return string
+     */
+    public function get_description() {
+        return 'User '.$this->objectid.' logged out.';
+    }
+
+    /**
+     * Returns relevant URL.
+     *
+     * @return \moodle_url
+     */
+    public function get_url() {
+        return new \moodle_url('/user/view.php', array('id' => $this->objectid));
+    }
+
+    /**
+     * Return name of the legacy event, which is replaced by this event.
+     *
+     * @return string legacy event name
+     */
+    public static function get_legacy_eventname() {
+        return 'user_logout';
+    }
+
+    /**
+     * Return user_logout legacy event data.
+     *
+     * @return \stdClass user data.
+     */
+    protected function get_legacy_eventdata() {
+        return $this->get_record_snapshot('user', $this->objectid);
+    }
+
+    /**
+     * Returns array of parameters to be passed to legacy add_to_log() function.
+     *
+     * @return array
+     */
+    protected function get_legacy_logdata() {
+        return array(SITEID, 'user', 'logout', 'view.php?id='.$this->objectid.'&course='.SITEID, $this->objectid, 0,
+            $this->objectid);
+    }
+}
diff --git a/lib/classes/event/user_updated.php b/lib/classes/event/user_updated.php
new file mode 100644 (file)
index 0000000..005ee40
--- /dev/null
@@ -0,0 +1,99 @@
+<?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/>.
+
+/**
+ * User updated event.
+ *
+ * @package    core
+ * @copyright  2013 Rajesh Taneja <rajesh@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace core\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Event when user profile 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 user_updated extends base {
+
+    /**
+     * Initialise required event data properties.
+     */
+    protected function init() {
+        $this->data['objecttable'] = 'user';
+        $this->data['crud'] = 'u';
+        $this->data['level'] = self::LEVEL_OTHER;
+    }
+
+    /**
+     * Returns localised event name.
+     *
+     * @return string
+     */
+    public static function get_name() {
+        return get_string('eventuserupdated');
+    }
+
+    /**
+     * Returns non-localised event description with id's for admin use only.
+     *
+     * @return string
+     */
+    public function get_description() {
+        return 'User profile updated for userid '.$this->objectid;
+    }
+
+    /**
+     * Returns relevant URL.
+     *
+     * @return \moodle_url
+     */
+    public function get_url() {
+        return new \moodle_url('/user/view.php', array('id' => $this->objectid));
+    }
+
+    /**
+     * Return name of the legacy event, which is replaced by this event.
+     *
+     * @return string legacy event name
+     */
+    public static function get_legacy_eventname() {
+        return 'user_updated';
+    }
+
+    /**
+     * Return user_updated legacy event data.
+     *
+     * @return \stdClass user data.
+     */
+    protected function get_legacy_eventdata () {
+        return $this->get_record_snapshot('user', $this->objectid);
+    }
+
+    /**
+     * Returns array of parameters to be passed to legacy add_to_log() function.
+     *
+     * @return array
+     */
+    protected function get_legacy_logdata() {
+        return array(SITEID, 'user', 'update', 'view.php?id='.$this->objectid, '');
+    }
+}
index b3ba54a..99e5f32 100644 (file)
@@ -36,14 +36,6 @@ defined('MOODLE_INTERNAL') || die();
 /* List of legacy event handlers */
 
 $handlers = array(
-
-    'user_updated' => array (
-        'handlerfile'      => '/lib/badgeslib.php',
-        'handlerfunction'  => 'badges_award_handle_profile_criteria_review',
-        'schedule'         => 'instant',
-        'internal'         => 1,
-    ),
-
 /*
  * portfolio queued event - for non interactive file transfers
  * NOTE: this is a HACK, please do not add any more things like this here
@@ -70,6 +62,10 @@ $observers = array(
     array(
         'eventname'   => '\core\event\course_completed',
         'callback'    => 'core_badges_observer::course_criteria_review',
+    ),
+    array(
+        'eventname'   => '\core\event\user_updated',
+        'callback'    => 'core_badges_observer::profile_criteria_review',
     )
 
 );
index a9741f9..1793749 100644 (file)
@@ -1276,16 +1276,7 @@ abstract class enrol_plugin {
         if ($ue = $DB->get_record('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$userid))) {
             //only update if timestart or timeend or status are different.
             if ($ue->timestart != $timestart or $ue->timeend != $timeend or (!is_null($status) and $ue->status != $status)) {
-                $ue->timestart    = $timestart;
-                $ue->timeend      = $timeend;
-                if (!is_null($status)) {
-                    $ue->status   = $status;
-                }
-                $ue->modifierid   = $USER->id;
-                $ue->timemodified = time();
-                $DB->update_record('user_enrolments', $ue);
-
-                $updated = true;
+                $this->update_user_enrol($instance, $userid, $status, $timestart, $timeend);
             }
         } else {
             $ue = new stdClass();
@@ -1303,16 +1294,17 @@ abstract class enrol_plugin {
         }
 
         if ($inserted) {
-            // add extra info and trigger event
-            $ue->courseid  = $courseid;
-            $ue->enrol     = $name;
-            events_trigger('user_enrolled', $ue);
-        } else if ($updated) {
-            $ue->courseid  = $courseid;
-            $ue->enrol     = $name;
-            events_trigger('user_enrol_modified', $ue);
-            // resets current enrolment caches
-            $context->mark_dirty();
+            // Trigger event.
+            $event = \core\event\user_enrolment_created::create(
+                    array(
+                        'objectid' => $ue->id,
+                        'courseid' => $courseid,
+                        'context' => $context,
+                        'relateduserid' => $ue->userid,
+                        'other' => array('enrol' => $name)
+                        )
+                    );
+            $event->trigger();
         }
 
         if ($roleid) {
@@ -1389,10 +1381,17 @@ abstract class enrol_plugin {
         $DB->update_record('user_enrolments', $ue);
         context_course::instance($instance->courseid)->mark_dirty(); // reset enrol caches
 
-        // trigger event
-        $ue->courseid  = $instance->courseid;
-        $ue->enrol     = $instance->name;
-        events_trigger('user_enrol_modified', $ue);
+        // Trigger event.
+        $event = \core\event\user_enrolment_updated::create(
+                array(
+                    'objectid' => $ue->id,
+                    'courseid' => $instance->courseid,
+                    'context' => context_course::instance($instance->courseid),
+                    'relateduserid' => $ue->userid,
+                    'other' => array('enrol' => $name)
+                    )
+                );
+        $event->trigger();
     }
 
     /**
@@ -1440,8 +1439,6 @@ abstract class enrol_plugin {
                  WHERE ue.userid = :userid AND e.courseid = :courseid";
         if ($DB->record_exists_sql($sql, array('userid'=>$userid, 'courseid'=>$courseid))) {
             $ue->lastenrol = false;
-            events_trigger('user_unenrolled', $ue);
-            // user still has some enrolments, no big cleanup yet
 
         } else {
             // the big cleanup IS necessary!
@@ -1458,9 +1455,20 @@ abstract class enrol_plugin {
             $DB->delete_records('user_lastaccess', array('userid'=>$userid, 'courseid'=>$courseid));
 
             $ue->lastenrol = true; // means user not enrolled any more
-            events_trigger('user_unenrolled', $ue);
         }
-
+        // Trigger event.
+        $event = \core\event\user_enrolment_deleted::create(
+                array(
+                    'courseid' => $courseid,
+                    'context' => $context,
+                    'relateduserid' => $ue->userid,
+                    'other' => array(
+                        'userenrolment' => (array)$ue,
+                        'enrol' => $name
+                        )
+                    )
+                );
+        $event->trigger();
         // reset all enrol caches
         $context->mark_dirty();
 
index abd2e3e..a0fae10 100644 (file)
@@ -3215,11 +3215,7 @@ function require_login($courseorid = null, $autologinguest = true, $cm = null, $
 function require_logout() {
     global $USER;
 
-    $params = $USER;
-
     if (isloggedin()) {
-        add_to_log(SITEID, "user", "logout", "view.php?id=$USER->id&course=".SITEID, $USER->id, 0, $USER->id);
-
         $authsequence = get_enabled_auth_plugins(); // Auths, in sequence.
         foreach ($authsequence as $authname) {
             $authplugin = get_auth_plugin($authname);
@@ -3227,9 +3223,16 @@ function require_logout() {
         }
     }
 
-    events_trigger('user_logout', $params);
+    $event = \core\event\user_loggedout::create(
+            array(
+                'objectid' => $USER->id,
+                'context' => context_user::instance($USER->id)
+                )
+            );
+    $event->trigger();
+
     session_get_instance()->terminate_current();
-    unset($params);
+    unset($GLOBALS['USER']);
 }
 
 /**
@@ -3442,7 +3445,9 @@ function get_user_key($script, $userid, $instance=null, $iprestriction=null, $va
  * @return bool Always returns true
  */
 function update_user_login_times() {
-    global $USER, $DB;
+    global $USER, $DB, $CFG;
+
+    require_once($CFG->dirroot.'/user/lib.php');
 
     if (isguestuser()) {
         // Do not update guest access times/ips for performance.
@@ -3468,7 +3473,7 @@ function update_user_login_times() {
     $USER->lastaccess = $user->lastaccess = $now;
     $USER->lastip = $user->lastip = getremoteaddr();
 
-    $DB->update_record('user', $user);
+    user_update_user($user, false);
     return true;
 }
 
@@ -3967,7 +3972,9 @@ function get_user_fieldnames() {
  */
 function create_user_record($username, $password, $auth = 'manual') {
     global $CFG, $DB;
-    require_once($CFG->dirroot."/user/profile/lib.php");
+    require_once($CFG->dirroot.'/user/profile/lib.php');
+    require_once($CFG->dirroot.'/user/lib.php');
+
     // Just in case check text case.
     $username = trim(core_text::strtolower($username));
 
@@ -4008,7 +4015,7 @@ function create_user_record($username, $password, $auth = 'manual') {
     $newuser->timemodified = $newuser->timecreated;
     $newuser->mnethostid = $CFG->mnet_localhost_id;
 
-    $newuser->id = $DB->insert_record('user', $newuser);
+    $newuser->id = user_create_user($newuser, false);
 
     // Save user profile data.
     profile_save_data($newuser);
@@ -4020,10 +4027,6 @@ function create_user_record($username, $password, $auth = 'manual') {
     // Set the password.
     update_internal_user_password($user, $password);
 
-    // Fetch full user record for the event, the complete user data contains too much info
-    // and we want to be consistent with other places that trigger this event.
-    events_trigger('user_created', $DB->get_record('user', array('id' => $user->id)));
-
     return $user;
 }
 
@@ -4036,6 +4039,7 @@ function create_user_record($username, $password, $auth = 'manual') {
 function update_user_record($username) {
     global $DB, $CFG;
     require_once($CFG->dirroot."/user/profile/lib.php");
+    require_once($CFG->dirroot.'/user/lib.php');
     // Just in case check text case.
     $username = trim(core_text::strtolower($username));
 
@@ -4078,14 +4082,10 @@ function update_user_record($username) {
         if ($newuser) {
             $newuser['id'] = $oldinfo->id;
             $newuser['timemodified'] = time();
-            $DB->update_record('user', $newuser);
+            user_update_user((object) $newuser, false);
 
             // Save user profile data.
             profile_save_data((object) $newuser);
-
-            // Fetch full user record for the event, the complete user data contains too much info
-            // and we want to be consistent with other places that trigger this event.
-            events_trigger('user_updated', $DB->get_record('user', array('id' => $oldinfo->id)));
         }
     }
 
@@ -4143,6 +4143,7 @@ function delete_user(stdClass $user) {
     require_once($CFG->libdir.'/gradelib.php');
     require_once($CFG->dirroot.'/message/lib.php');
     require_once($CFG->dirroot.'/tag/lib.php');
+    require_once($CFG->dirroot.'/user/lib.php');
 
     // Make sure nobody sends bogus record type as parameter.
     if (!property_exists($user, 'id') or !property_exists($user, 'username')) {
@@ -4169,6 +4170,9 @@ function delete_user(stdClass $user) {
         return false;
     }
 
+    // Keep a copy of user context, we need it for event.
+    $usercontext = context_user::instance($user->id);
+
     // Delete all grades - backup is kept in grade_grades_history table.
     grade_user_delete($user->id);
 
@@ -4218,9 +4222,6 @@ function delete_user(stdClass $user) {
     // Force logout - may fail if file based sessions used, sorry.
     session_kill_user($user->id);
 
-    // Now do a final accesslib cleanup - removes all role assignments in user context and context itself.
-    context_helper::delete_instance(CONTEXT_USER, $user->id);
-
     // Workaround for bulk deletes of users with the same email address.
     $delname = "$user->email.".time();
     while ($DB->record_exists('user', array('username' => $delname))) { // No need to use mnethostid here.
@@ -4237,9 +4238,22 @@ function delete_user(stdClass $user) {
     $updateuser->picture      = 0;
     $updateuser->timemodified = time();
 
-    $DB->update_record('user', $updateuser);
-    // Add this action to log.
-    add_to_log(SITEID, 'user', 'delete', "view.php?id=$user->id", $user->firstname.' '.$user->lastname);
+    user_update_user($updateuser, false);
+
+    // Now do a final accesslib cleanup - removes all role assignments in user context and context itself.
+    context_helper::delete_instance(CONTEXT_USER, $user->id);
+
+    // Any plugin that needs to cleanup should register this event.
+    // Trigger event.
+    $event = \core\event\user_deleted::create(
+            array(
+                'objectid' => $user->id,
+                'context' => $usercontext,
+                'other' => array('user' => (array)clone $user)
+                )
+            );
+    $event->add_record_snapshot('user', $updateuser);
+    $event->trigger();
 
     // We will update the user's timemodified, as it will be passed to the user_deleted event, which
     // should know about this updated property persisted to the user's table.
@@ -4249,9 +4263,6 @@ function delete_user(stdClass $user) {
     $authplugin = get_auth_plugin($user->auth);
     $authplugin->user_delete($user);
 
-    // Any plugin that needs to cleanup should register this event.
-    events_trigger('user_deleted', $user);
-
     return true;
 }
 
index 50b1be9..2a70acc 100644 (file)
@@ -1851,7 +1851,14 @@ class core_moodlelib_testcase extends advanced_testcase {
         $user = $this->getDataGenerator()->create_user(array('idnumber'=>'abc'));
         $user2 = $this->getDataGenerator()->create_user(array('idnumber'=>'xyz'));
 
+        // Delete user and capture event.
+        $sink = $this->redirectEvents();
         $result = delete_user($user);
+        $events = $sink->get_events();
+        $sink->close();
+        $event = array_pop($events);
+
+        // Test user is deleted in DB.
         $this->assertTrue($result);
         $deluser = $DB->get_record('user', array('id'=>$user->id), '*', MUST_EXIST);
         $this->assertEquals(1, $deluser->deleted);
@@ -1862,8 +1869,15 @@ class core_moodlelib_testcase extends advanced_testcase {
 
         $this->assertEquals(1, $DB->count_records('user', array('deleted'=>1)));
 
-        // Try invalid params.
+        // Test Event.
+        $this->assertInstanceOf('\core\event\user_deleted', $event);
+        $this->assertSame($user->id, $event->objectid);
+        $this->assertSame('user_deleted', $event->get_legacy_eventname());
+        $this->assertEventLegacyData($user, $event);
+        $expectedlogdata = array(SITEID, 'user', 'delete', "view.php?id=$user->id", $user->firstname.' '.$user->lastname);
+        $this->assertEventLegacyLogData($expectedlogdata, $event);
 
+        // Try invalid params.
         $record = new stdClass();
         $record->grrr = 1;
         try {
@@ -2407,4 +2421,35 @@ class core_moodlelib_testcase extends advanced_testcase {
         $expectedarray = array('19' => 'second', '38' => 'first', '44' => 'firsthalf');
         $this->assertEquals($expectedarray, order_in_string($valuearray, $formatstring));
     }
+
+    /**
+     * Test require_logout.
+     */
+    public function test_require_logout() {
+        $this->resetAfterTest();
+        $user = $this->getDataGenerator()->create_user();
+        $this->setUser($user);
+        $course = $this->getDataGenerator()->create_course();
+
+        $this->assertTrue(isloggedin());
+
+        // Logout user and capture event.
+        $sink = $this->redirectEvents();
+        require_logout();
+        $events = $sink->get_events();
+        $sink->close();
+        $event = array_pop($events);
+
+        // Check if user is logged out.
+        $this->assertFalse(isloggedin());
+
+        // Test Event.
+        $this->assertInstanceOf('\core\event\user_loggedout', $event);
+        $this->assertSame($user->id, $event->objectid);
+        $this->assertSame('user_logout', $event->get_legacy_eventname());
+        $this->assertEventLegacyData($user, $event);
+        $expectedlogdata = array(SITEID, 'user', 'logout', 'view.php?id='.$event->objectid.'&course='.SITEID, $event->objectid, 0,
+            $event->objectid);
+        $this->assertEventLegacyLogData($expectedlogdata, $event);
+    }
 }
diff --git a/mod/forum/classes/observer.php b/mod/forum/classes/observer.php
new file mode 100644 (file)
index 0000000..a41efff
--- /dev/null
@@ -0,0 +1,52 @@
+<?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/>.
+
+/**
+ * Event observers used in forum.
+ *
+ * @package    mod_forum
+ * @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 mod_forum.
+ */
+class mod_forum_observer {
+    /**
+     * Triggered via user_enrolment_deleted event.
+     *
+     * @param \core\event\user_enrolment_deleted $event
+     */
+    public static function user_enrolment_deleted(\core\event\user_enrolment_deleted $event) {
+        global $DB;
+
+        // NOTE: this has to be as fast as possible.
+        // Get user enrolment info from event.
+        $cp = (object)$event->other['userenrolment'];
+        if ($cp->lastenrol) {
+            $params = array('userid' => $cp->userid, 'courseid' => $cp->courseid);
+            $forumselect = "IN (SELECT f.id FROM {forum} f WHERE f.course = :courseid)";
+
+            $DB->delete_records_select('forum_digests', 'userid = :userid AND forum '.$forumselect, $params);
+            $DB->delete_records_select('forum_subscriptions', 'userid = :userid AND forum '.$forumselect, $params);
+            $DB->delete_records_select('forum_track_prefs', 'userid = :userid AND forumid '.$forumselect, $params);
+            $DB->delete_records_select('forum_read', 'userid = :userid AND forumid '.$forumselect, $params);
+        }
+    }
+}
index ded6583..5421b5a 100644 (file)
@@ -31,11 +31,13 @@ $handlers = array (
         'schedule'         => 'instant',
         'internal'         => 1,
     ),
+);
 
-    'user_unenrolled' => array (
-        'handlerfile'      => '/mod/forum/lib.php',
-        'handlerfunction'  => 'forum_user_unenrolled',
-        'schedule'         => 'instant',
-        'internal'         => 1,
+// List of observers.
+$observers = array(
+
+    array(
+        'eventname'   => '\core\event\user_enrolment_deleted',
+        'callback'    => 'mod_forum_observer::user_enrolment_deleted',
     ),
 );
index 917bb8a..be0a2ea 100644 (file)
@@ -6289,28 +6289,6 @@ function forum_user_role_assigned($cp) {
     }
 }
 
-/**
- * This function gets run whenever user is unenrolled from course
- *
- * @param stdClass $cp
- * @return void
- */
-function forum_user_unenrolled($cp) {
-    global $DB;
-
-    // NOTE: this has to be as fast as possible!
-
-    if ($cp->lastenrol) {
-        $params = array('userid'=>$cp->userid, 'courseid'=>$cp->courseid);
-        $forumselect = "IN (SELECT f.id FROM {forum} f WHERE f.course = :courseid)";
-
-        $DB->delete_records_select('forum_digests',       "userid = :userid AND forum $forumselect", $params);
-        $DB->delete_records_select('forum_subscriptions', "userid = :userid AND forum $forumselect", $params);
-        $DB->delete_records_select('forum_track_prefs',   "userid = :userid AND forumid $forumselect", $params);
-        $DB->delete_records_select('forum_read',          "userid = :userid AND forumid $forumselect", $params);
-    }
-}
-
 // Functions to do with read tracking.
 
 /**
index 90de875..d5bfb7a 100644 (file)
@@ -168,4 +168,37 @@ class mod_forum_lib_testcase extends advanced_testcase {
             $this->assertContains($course->shortname, array($course1->shortname, $course2->shortname));
         }
     }
+
+    /**
+     * Test user_enrolment_deleted observer.
+     */
+    public function test_user_enrolment_deleted_observer() {
+        global $DB;
+
+        $this->resetAfterTest();
+
+        $metaplugin = enrol_get_plugin('meta');
+        $user1 = $this->getDataGenerator()->create_user();
+        $course1 = $this->getDataGenerator()->create_course();
+        $course2 = $this->getDataGenerator()->create_course();
+        $student = $DB->get_record('role', array('shortname'=>'student'));
+
+        $e1 = $metaplugin->add_instance($course2, array('customint1' => $course1->id));
+        $enrol1 = $DB->get_record('enrol', array('id' => $e1));
+
+        // Enrol user.
+        $metaplugin->enrol_user($enrol1, $user1->id, $student->id);
+        $this->assertEquals(1, $DB->count_records('user_enrolments'));
+
+        // Unenrol user and capture event.
+        $sink = $this->redirectEvents();
+        $metaplugin->unenrol_user($enrol1, $user1->id);
+        $events = $sink->get_events();
+        $sink->close();
+        $event = array_pop($events);
+
+        $this->assertEquals(0, $DB->count_records('user_enrolments'));
+        $this->assertInstanceOf('\core\event\user_enrolment_deleted', $event);
+        $this->assertEquals('user_unenrolled', $event->get_legacy_eventname());
+    }
 }
index 49758e2..821ba4d 100644 (file)
@@ -28,6 +28,7 @@ require_once($CFG->libdir.'/gdlib.php');
 require_once($CFG->dirroot.'/user/edit_form.php');
 require_once($CFG->dirroot.'/user/editlib.php');
 require_once($CFG->dirroot.'/user/profile/lib.php');
+require_once($CFG->dirroot.'/user/lib.php');
 
 //HTTPS is required in this page when $CFG->loginhttps enabled
 $PAGE->https_required();
@@ -177,8 +178,6 @@ $email_changed = false;
 
 if ($usernew = $userform->get_data()) {
 
-    add_to_log($course->id, 'user', 'update', "view.php?id=$user->id&course=$course->id", '');
-
     $email_changed_html = '';
 
     if ($CFG->emailchangeconfirmation) {
@@ -206,15 +205,15 @@ if ($usernew = $userform->get_data()) {
         $usernew = file_postupdate_standard_editor($usernew, 'description', $editoroptions, $personalcontext, 'user', 'profile', 0);
     }
 
-    $DB->update_record('user', $usernew);
-
-    // pass a true $userold here
-    if (! $authplugin->user_update($user, $usernew)) {
-        // auth update failed, rollback for moodle
-        $DB->update_record('user', $user);
+    // Pass a true old $user here.
+    if (!$authplugin->user_update($user, $usernew)) {
+        // Auth update failed.
         print_error('cannotupdateprofile');
     }
 
+    // Update user with new profile data.
+    user_update_user($usernew, false);
+
     //update preferences
     useredit_update_user_preference($usernew);
 
@@ -259,7 +258,6 @@ if ($usernew = $userform->get_data()) {
 
     // reload from db
     $usernew = $DB->get_record('user', array('id'=>$user->id));
-    events_trigger('user_updated', $usernew);
 
     if ($USER->id == $user->id) {
         // Override old $USER session variable if needed
index 9409937..9728bbd 100644 (file)
@@ -29,6 +29,7 @@ require_once($CFG->libdir.'/adminlib.php');
 require_once($CFG->dirroot.'/user/editadvanced_form.php');
 require_once($CFG->dirroot.'/user/editlib.php');
 require_once($CFG->dirroot.'/user/profile/lib.php');
+require_once($CFG->dirroot.'/user/lib.php');
 
 //HTTPS is required in this page when $CFG->loginhttps enabled
 $PAGE->https_required();
@@ -177,20 +178,15 @@ if ($usernew = $userform->get_data()) {
         } else {
             $usernew->password = hash_internal_user_password($usernew->newpassword);
         }
-        $usernew->id = $DB->insert_record('user', $usernew);
-        $usercreated = true;
-        add_to_log($course->id, 'user', 'add', "view.php?id=$usernew->id&course=$course->id", '');
-
+        $usernew->id = user_create_user($usernew, false);
     } else {
         $usernew = file_postupdate_standard_editor($usernew, 'description', $editoroptions, $usercontext, 'user', 'profile', 0);
-        $DB->update_record('user', $usernew);
-        // pass a true $userold here
-        if (! $authplugin->user_update($user, $userform->get_data())) {
-            // auth update failed, rollback for moodle
-            $DB->update_record('user', $user);
+        // Pass a true old $user here.
+        if (!$authplugin->user_update($user, $usernew)) {
+            // Auth update failed.
             print_error('cannotupdateuseronexauth', '', '', $user->auth);
         }
-        add_to_log($course->id, 'user', 'update', "view.php?id=$user->id&course=$course->id", '');
+        user_update_user($usernew, false);
 
         //set new password if specified
         if (!empty($usernew->newpassword)) {
@@ -206,8 +202,6 @@ if ($usernew = $userform->get_data()) {
         if (isset($usernew->suspended) and $usernew->suspended and !$user->suspended) {
             session_kill_user($user->id);
         }
-
-        $usercreated = false;
     }
 
     $usercontext = context_user::instance($usernew->id);
@@ -237,13 +231,6 @@ if ($usernew = $userform->get_data()) {
     // reload from db
     $usernew = $DB->get_record('user', array('id'=>$usernew->id));
 
-    // trigger events
-    if ($usercreated) {
-        events_trigger('user_created', $usernew);
-    } else {
-        events_trigger('user_updated', $usernew);
-    }
-
     if ($createpassword) {
         setnew_password_and_mail($usernew);
         unset_user_preference('create_password', $usernew);
index 0aee6c8..256af0f 100644 (file)
@@ -26,6 +26,7 @@
 require_once('../config.php');
 require_once($CFG->libdir.'/adminlib.php');
 require_once($CFG->dirroot.'/user/editlib.php');
+require_once($CFG->dirroot.'/user/lib.php');
 
 $key = required_param('key', PARAM_ALPHANUM);
 $id  = required_param('id', PARAM_INT);
@@ -60,17 +61,16 @@ if (empty($preferences['newemailattemptsleft'])) {
     cancel_email_update($user->id);
     $user->email = $preferences['newemail'];
 
-    // Detect duplicate before saving
+    // Detect duplicate before saving.
     if ($DB->get_record('user', array('email' => $user->email))) {
         $stremailnowexists = get_string('emailnowexists', 'auth');
         echo $OUTPUT->box($stremailnowexists, 'center');
         echo $OUTPUT->continue_button("$CFG->wwwroot/user/view.php?id=$user->id");
     } else {
-        // update user email
-        $DB->set_field('user', 'email', $user->email, array('id' => $user->id));
+        // Update user email.
         $authplugin = get_auth_plugin($user->auth);
         $authplugin->user_update($olduser, $user);
-        events_trigger('user_updated', $user);
+        user_update_user($user, false);
         $a->email = $user->email;
         $stremailupdatesuccess = get_string('emailupdatesuccess', 'auth', $a);
         echo $OUTPUT->box($stremailupdatesuccess, 'center');
index 737a98a..7ab6c0d 100644 (file)
 /**
  * Creates a user
  *
- * @param object $user user to create
+ * @param stdClass $user user to create
+ * @param bool $updatepassword if true, authentication plugin will update password.
  * @return int id of the newly created user
  */
-function user_create_user($user) {
+function user_create_user($user, $updatepassword = true) {
     global $DB;
 
-    // set the timecreate field to the current time
+    // Set the timecreate field to the current time.
     if (!is_object($user)) {
             $user = (object)$user;
     }
 
-    //check username
+    // Check username.
     if ($user->username !== core_text::strtolower($user->username)) {
         throw new moodle_exception('usernamelowercase');
     } else {
@@ -48,10 +49,10 @@ function user_create_user($user) {
         }
     }
 
-    // save the password in a temp value for later
-    if (isset($user->password)) {
+    // Save the password in a temp value for later.
+    if ($updatepassword && isset($user->password)) {
 
-        //check password toward the password policy
+        // Check password toward the password policy.
         if (!check_password_policy($user->password, $errmsg)) {
             throw new moodle_exception($errmsg);
         }
@@ -63,36 +64,39 @@ function user_create_user($user) {
     $user->timecreated = time();
     $user->timemodified = $user->timecreated;
 
-    // insert the user into the database
+    // Insert the user into the database.
     $newuserid = $DB->insert_record('user', $user);
 
-    // trigger user_created event on the full database user row
-    $newuser = $DB->get_record('user', array('id' => $newuserid));
+    // Create USER context for this user.
+    $usercontext = context_user::instance($newuserid);
 
-    // create USER context for this user
-    context_user::instance($newuserid);
-
-    // update user password if necessary
+    // Update user password if necessary.
     if (isset($userpassword)) {
+        // Get full database user row, in case auth is default.
+        $newuser = $DB->get_record('user', array('id' => $newuserid));
         $authplugin = get_auth_plugin($newuser->auth);
         $authplugin->user_update_password($newuser, $userpassword);
     }
 
-    events_trigger('user_created', $newuser);
-
-    add_to_log(SITEID, 'user', get_string('create'), '/view.php?id='.$newuser->id,
-        fullname($newuser));
+    // Trigger event.
+    $event = \core\event\user_created::create(
+            array(
+                'objectid' => $newuserid,
+                'context' => $usercontext
+                )
+            );
+    $event->trigger();
 
     return $newuserid;
-
 }
 
 /**
  * Update a user with a user object (will compare against the ID)
  *
- * @param object $user the user to update
+ * @param stdClass $user the user to update
+ * @param bool $updatepassword if true, authentication plugin will update password.
  */
-function user_update_user($user) {
+function user_update_user($user, $updatepassword = true) {
     global $DB;
 
     // set the timecreate field to the current time
@@ -111,8 +115,8 @@ function user_update_user($user) {
         }
     }
 
-    // unset password here, for updating later
-    if (isset($user->password)) {
+    // Unset password here, for updating later, if password update is required.
+    if ($updatepassword && isset($user->password)) {
 
         //check password toward the password policy
         if (!check_password_policy($user->password, $errmsg)) {
@@ -126,22 +130,27 @@ function user_update_user($user) {
     $user->timemodified = time();
     $DB->update_record('user', $user);
 
-    // trigger user_updated event on the full database user row
-    $updateduser = $DB->get_record('user', array('id' => $user->id));
+    if ($updatepassword) {
+        // Get full user record.
+        $updateduser = $DB->get_record('user', array('id' => $user->id));
 
-    // if password was set, then update its hash
-    if (isset($passwd)) {
-        $authplugin = get_auth_plugin($updateduser->auth);
-        if ($authplugin->can_change_password()) {
-            $authplugin->user_update_password($updateduser, $passwd);
+        // if password was set, then update its hash
+        if (isset($passwd)) {
+            $authplugin = get_auth_plugin($updateduser->auth);
+            if ($authplugin->can_change_password()) {
+                $authplugin->user_update_password($updateduser, $passwd);
+            }
         }
     }
 
-    events_trigger('user_updated', $updateduser);
-
-    add_to_log(SITEID, 'user', get_string('update'), '/view.php?id='.$updateduser->id,
-        fullname($updateduser));
-
+    // Trigger event.
+    $event = \core\event\user_updated::create(
+            array(
+                'objectid' => $user->id,
+                'context' => context_user::instance($user->id)
+                )
+            );
+    $event->trigger();
 }
 
 /**
diff --git a/user/tests/userlib_test.php b/user/tests/userlib_test.php
new file mode 100644 (file)
index 0000000..9959d0f
--- /dev/null
@@ -0,0 +1,132 @@
+<?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/>.
+
+/**
+ * Unit tests for user/lib.php.
+ *
+ * @package    core_user
+ * @category   phpunit
+ * @copyright  2013 Rajesh Taneja <rajesh@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->dirroot.'/user/lib.php');
+
+/**
+ * Unit tests for user lib api.
+ *
+ * @package    core_user
+ * @category   phpunit
+ * @copyright  2013 Rajesh Taneja <rajesh@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class core_userliblib_testcase extends advanced_testcase {
+    /**
+     * Test user_update_user.
+     */
+    public function test_user_update_user() {
+        global $DB;
+
+        $this->resetAfterTest();
+
+        // Create user and modify user profile.
+        $user = $this->getDataGenerator()->create_user();
+        $user->firstname = 'Test';
+        $user->password = 'M00dLe@T';
+
+        // Update user and capture event.
+        $sink = $this->redirectEvents();
+        user_update_user($user);
+        $events = $sink->get_events();
+        $sink->close();
+        $event = array_pop($events);
+
+        // Test updated value.
+        $dbuser = $DB->get_record('user', array('id' => $user->id));
+        $this->assertSame($user->firstname, $dbuser->firstname);
+        $this->assertNotSame('M00dLe@T', $dbuser->password);
+
+        // Test event.
+        $this->assertInstanceOf('\core\event\user_updated', $event);
+        $this->assertSame($user->id, $event->objectid);
+        $this->assertSame('user_updated', $event->get_legacy_eventname());
+        $this->assertEventLegacyData($dbuser, $event);
+        $this->assertEquals(context_user::instance($user->id), $event->get_context());
+        $expectedlogdata = array(SITEID, 'user', 'update', 'view.php?id='.$user->id, '');
+        $this->assertEventLegacyLogData($expectedlogdata, $event);
+
+        // Update user with no password update.
+        $password = $user->password = hash_internal_user_password('M00dLe@T');
+        user_update_user($user, false);
+        $dbuser = $DB->get_record('user', array('id' => $user->id));
+        $this->assertSame($password, $dbuser->password);
+    }
+
+    /**
+     * Test create_users.
+     */
+    public function test_create_users() {
+        global $DB;
+
+        $this->resetAfterTest();
+
+        $user = array(
+            'username' => 'usernametest1',
+            'password' => 'Moodle2012!',
+            'idnumber' => 'idnumbertest1',
+            'firstname' => 'First Name User Test 1',
+            'lastname' => 'Last Name User Test 1',
+            'middlename' => 'Middle Name User Test 1',
+            'lastnamephonetic' => '最後のお名前のテスト一号',
+            'firstnamephonetic' => 'お名前のテスト一号',
+            'alternatename' => 'Alternate Name User Test 1',
+            'email' => 'usertest1@email.com',
+            'description' => 'This is a description for user 1',
+            'city' => 'Perth',
+            'country' => 'au'
+            );
+
+        // Create user and capture event.
+        $sink = $this->redirectEvents();
+        $user['id'] = user_create_user($user);
+        $events = $sink->get_events();
+        $sink->close();
+        $event = array_pop($events);
+
+        // Test user info in DB.
+        $dbuser = $DB->get_record('user', array('id' => $user['id']));
+        $this->assertEquals($dbuser->username, $user['username']);
+        $this->assertEquals($dbuser->idnumber, $user['idnumber']);
+        $this->assertEquals($dbuser->firstname, $user['firstname']);
+        $this->assertEquals($dbuser->lastname, $user['lastname']);
+        $this->assertEquals($dbuser->email, $user['email']);
+        $this->assertEquals($dbuser->description, $user['description']);
+        $this->assertEquals($dbuser->city, $user['city']);
+        $this->assertEquals($dbuser->country, $user['country']);
+
+        // Test event.
+        $this->assertInstanceOf('\core\event\user_created', $event);
+        $this->assertEquals($user['id'], $event->objectid);
+        $this->assertEquals('user_created', $event->get_legacy_eventname());
+        $this->assertEquals(context_user::instance($user['id']), $event->get_context());
+        $this->assertEventLegacyData($dbuser, $event);
+        $expectedlogdata = array(SITEID, 'user', 'add', '/view.php?id='.$event->objectid, fullname($dbuser));
+        $this->assertEventLegacyLogData($expectedlogdata, $event);
+    }
+}