Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Events API: Difference between revisions

From MoodleDocs
Line 45: Line 45:
** System log
** System log
* '''Datetime*''' (milliseconds? DateTime object? Let's keep in mind that timestamps are unreliable as they don't include timezone!)
* '''Datetime*''' (milliseconds? DateTime object? Let's keep in mind that timestamps are unreliable as they don't include timezone!)
* Context ID*
* '''Context ID*'''
* Category ID
* Category ID
* Category name
* Category name

Revision as of 07:32, 20 May 2013

Events and Event-based Logging. Specification for 2.6

Introduction

  • Starting from Moodle 2.6 logging is implemented in form of event-listening by plugins. The events will be objects with much more details than in 2.5- and much more specific.
  • Logging is performed by plugins listening to events.
  • In 2.6 it will also be possible to subscribe to '*' event (which means everything).
  • Everywhere where in 2.5 we add information to log or trigger an event we must generate the new event. For backward compartibility it will also contain information in the 2.5 format.

Standard Moodle distribution will include simple DB logging plugin storing the data in new format and legacy logging plugin storing the data in old format in {log} table. Old standard reports will use the new event logging. All custom reports will be able to work with {log} table using legacy logging plugin.

Triggering events

  • All events descriptions are objects extending event_base (which is defined in core)
  • Object class name is unique identifier of the event
  • Class name is pluginfullname_event_xxx. Core events will have prefix 'moodle'
  • Plugins store each event object in plugindir/classes/event/xxx.php

Backward compartibility:

  • Function events_trigger() will create and trigger an instance of event_legacy class
  • For events that already exist in Moodle 2.5 the additional legacy information should be added to the event data (in properties 'legacyname' and 'legacydata')

Handling (observing) events

  • Event handlers can be described as it is done now in plugindir/db/events.php, this file is parsed during install/upgrade of plugin and all handlers are removed on uninstall
  • It is possible to subscribe to all events (*)
  • Event handlers can also have an attribute 'sortorder' (positive or negative, default 0). At the same time admin can overwrite the handlers sequence
  • If event handler refers to the old (2.5) name of event, it will be used only for events that contain legacy name and data. If it refers to 2.6 event class name it will be used with full data
  • It is also possible to dynamically register/unregister handlers but they are not recommended (same as it is with dynamic caches definitions). Ideally they should only be used in unit and/or behat tests

Event properties

Those are the fields that an event could define. Depending on the type of event, some can be optional and some can be mandatory. Not all of the mandatory fields have to be set when triggering the event as some logic can help defining them in the constructor. For example, we can use $USER to find out what user is currently logged in.

There are suggested list of properties, with some mandatory fields (*) defined for the base class.

  • Event specification version number*
  • Event name*
  • Type*
    • Error
    • User action
      • Procedural action
      • Manual action
    • System log
  • Datetime* (milliseconds? DateTime object? Let's keep in mind that timestamps are unreliable as they don't include timezone!)
  • Context ID*
  • Category ID
  • Category name
  • Course ID*
  • Course name
  • Course module ID*
  • Course module name
  • Component*
    • core
    • course
    • mod_assign
    • mod_workshop
  • Subject* (Defines the object on which the action is performed)
    • user
    • section
    • assignment
    • submission_phase
  • Subject ID*
  • Subject name (Human readable identifier of the object: Mark Johnson, Course ABC, ...)
  • Subject URL (URL to notice the changes)
  • Action* (The exact action that is performed on the object)
    • created
    • moved (for a course, a section, a module, a user between groups)
    • submitted (for an assignment, or a message)
    • ended (for a submission phase for instance)
  • Actor* (user, cli, cron, ...)
  • Actor ID/User ID* (ID assiacted to the actor, typically the user id)
  • Real actor/user ID* (When logged in as, store the real user ID)
  • Actor IP address*
  • Associated object (Object associated to the subject. Ie: category of origin when a course is moved. User to whom a message is sent.)
    • section
    • category
    • user (to whom you sent a message)
  • Associated object ID
  • Transaction type* (CRUD)
    • create
    • read
    • update
    • delete
  • Level* (Not convinced that we should use that, because it's very subjective, except if we have guidelines and only a few levels (2, max 3))
    • major
    • normal
    • minor
  • Message (human readable log)
  • Data (serialized/JSON'd data for more any extra field specific to this event)
  • Current URL

Data

The field data should be a placeholder for any extra information which is specific to the event. This array/object of values could describe in more details an entry which has been deleted by storing the data, or an entry updated by storing the differences, etc.... This data could ideally be converted to JSON (by a logger) to easily be stored, which means that PHP Objects cannot be included in there. We would not rely on serialized data as they have been proven not reliable.

event_base class

abstract class event_base implements cacheable_object {
  // ... constants and all properties as protected variables
  protected final function __construct() {}
  protected function __construct($args);
  public static final function create($args) {
    return new self($args);
  }
  public static final funciton restore($object) {
    $event = new self();
    // .. restore each property from $object to $event
  }
  public static final function create_and_trigger($args) {
    $event = self::create($args);
    $event->trigger();
  }
  public final function trigger() {
    // ... 
  }
  public static function event_name();
  public static function event_description();
  public function can_view($user = null);
  public function event_data();
  public function prepare_to_cache() {
    // .. basic implementation caching ALL fields
  }
  public static function wake_from_cache($a) {
    // .. basic implementation restoring ALL fields
  }
}