This is a test site. Any changes will be lost!

Development:Events: Difference between revisions

From MoodleDocs
Flagging this article as Obsolete design
 
(44 intermediate revisions by 10 users not shown)
Line 1: Line 1:
{{obsolete_design}}
{{Moodle 1.9}}
The Events API is a new core system in Moodle to allow better communication between modules.  It's based on modules triggering new events with attached data, and the other modules handling those events with custom functions.
The Events API is a new core system in Moodle to allow better communication between modules.  It's based on modules triggering new events with attached data, and the other modules handling those events with custom functions.


Line 9: Line 11:
Whenever a grade is created or changed by a module, it should “tell” the system about it (in addition to any local working storage it uses).  So, using the quiz as an example, we first define an object as follows:
Whenever a grade is created or changed by a module, it should “tell” the system about it (in addition to any local working storage it uses).  So, using the quiz as an example, we first define an object as follows:


  $eventdata = new object;
  $eventdata = new object();
  $eventdata->courseid = $course->id;
  $eventdata->itemid = $grade_item->id;
$eventdata->itemname = $quiz->name;
$eventdata->itemtype = 'mod';
$eventdata->itemmodule = 'quiz';
$eventdata->iteminstance = $quiz->id;
$eventdata->itemnumber = 1;
$eventdata->iteminfo = $quiz->info;
$eventdata->idnumber = $cm->idnumber;  // new field in 1.9
$eventdata->grademax = $quiz->grade;
$eventdata->grademin = 0;
  $eventdata->userid = $USER->id;
  $eventdata->userid = $USER->id;
  $eventdata->gradevalue = $currentvalue;
  $eventdata->gradevalue = $currentvalue;
Line 25: Line 18:
Then we post the object as an event and forget about it:
Then we post the object as an event and forget about it:


  trigger_event('grade_added', $eventdata);
  events_trigger('grade_updated', $eventdata);
 


===Handling an event===
===Handling an event===
Line 32: Line 24:
Modules can define an events.php in their db directory which defines events they want to be notified about, and describes which of their functions or class methods should be notified.  For example, an export  plugin could register something like:
Modules can define an events.php in their db directory which defines events they want to be notified about, and describes which of their functions or class methods should be notified.  For example, an export  plugin could register something like:


  $events = array (
  $handlers = array (
    'grade_added' => array (
    'grade_updated' => array (
         'file'       => '/grade/export/banner/lib.php',
         'handlerfile'     => '/grade/export/banner/lib.php',
         'function'  => 'banner_handle_grade',    // argument to call_user_func(), could be an array
         'handlerfunction'  => 'banner_handle_grade_test',    // argument to call_user_func(), could be an array
         'timing'   => 'cron'
         'schedule'         => 'cron'
     );
     )  
  );
  );
These are parsed during install / upgrade and stored in a simple database table.
These are parsed during install / upgrade and stored in a simple database table.


Then, when a grade_added event happens, all the registered functions for that event will be called something like this (but with more error handling):
Then, when a grade_updated event happens, all the registered functions for that event will be called something like this (but with more error handling):
 
          include_once($CFG->dirroot.$events['grade_added']['file'];
          call_user_func($events['grade_added']['function'], $eventdata);
 
All plugins in Moodle have access to this and can this easily “hook in” to 'grade_added' events (and of course any other events).
 
==Standards for naming events==


All event names should follow a consistent naming pattern, such as modulename_noun_verb
          include_once($CFG->dirroot.$handlers['grade_updated']['handlerfile']);
          call_user_func($handlers['grade_updated']['handlerfunction'], $eventdata);


All plugins in Moodle have access to this and can this easily “hook in” to 'grade_updated' events (and of course any other events).


==Database structure==
==Database structure==


There are 2 core tables for events.
There are 3 core tables for events. Note that if a handler is queued, and yet to be processed or processing failed, then all subsequent calls on that handler must be queued.


===events_handlers===
===events_handlers===


This table is for storing which components requests what type of event, and the location of the responsible handlers. For example, the grade book can register 'grade_added' event with a function add_grade() that should be called event time an 'grade_added' event is triggered by a module.
This table is for storing which components requests what type of event, and the location of the responsible handlers. For example, the grade book can register 'grade_added' event with a function add_grade() that should be called any time an 'grade_added' event is triggered by a module.
 
These entries are created by parsing events.php files in all the modules, and can be rebuilt any time (during an upgrade, say).


{| border="1" cellpadding="2" cellspacing="0"
{| border="1" cellpadding="2" cellspacing="0"
Line 73: Line 61:
|eventname
|eventname
|varchar(255)
|varchar(255)
|name of the event, e.g. 'grade_added'
|name of the event, e.g. 'grade_updated'
|-
|-
|handlermodule
|handlermodule
Line 86: Line 74:
|text
|text
|serialized string or array describing function, suitable to be passed to '''call_user_func()'''
|serialized string or array describing function, suitable to be passed to '''call_user_func()'''
|-
|schedule
|varchar(255)
|'cron' or 'instant'.
|-
|status
|int(10)
|number of failed attempts to process this handler
|}
|}


===events_queue===
===events_queue===


The event queue table should put all responding events into the queue. For example, an event triggered by grade book 'grade_updated' can result in the response of all modules. Each response should be either queued or processed instantly. If an "instant" event is not processed successfully it is then queued. So a 'grade_updated' event could insert multiple records into the event_queue table. The status field counts failures - if the failures reach some high number then some action should be taken (alert the admin etc).
This table is for storing queued events. It stores only one copy of the eventdata here, and entries from this table are being references by the events_queue_handlers table.
 
{| border="1" cellpadding="2" cellspacing="0"
|'''Field'''
|'''Type'''
|'''Info'''
|-
|id
|int(10)
|auto increment identifier
|-
|eventdata
|longtext
|serialized version of the data object passed to the event handler.
|-
|stackdump
|text
|serialized debug_backtrace showing where the event was fired from
|-
|userid
|int(10)
|$USER->id when the event was fired
|-
|timecreated
|int(10)
|time stamp of the first time this was added
|}
 
===events_queue_handlers===


  id - auto increment identifier
This is the list of queued handlers for processing. The event object is retrieved from the events_queue table. When no further reference is made to the events_queue table, the corresponding entry in the events_queue table should be deleted. Entry should get deleted (?) after a successful event processing by the specified handler. The status field keeps track of failures, after it gets to a certain number (eg 10?) it should trigger an "event failed" event (that could result in admin being emailed etc, or perhaps even the originating module taking care of it or rolling something back etc).
handlerid - foreign key id corresponding to the id of the event_handlers table
 
eventdata - serialized version of the data object passed to the event handler.
{| border="1" cellpadding="2" cellspacing="0"
schedule - 'cron' or 'instant'.
|'''Field'''
status - number of failed attempts to process this handler
|'''Type'''
timecreated - time stamp of the first time this was added
|'''Info'''
timemodified - time stamp of the last attempt to run this from the queue
|-
|id
|int(10)
|auto increment identifier
|-
|queuedeventid
|int(10)
|foreign key id corresponding to the id of the event_queues table
|-
|handlerid
|int(10)
|foreign key id corresponding to the id of the event_handlers table
|-
|status
|int(10)
|number of failed attempts to process this handler
|-
|errormessage
|text
|if an error happened last time we tried to process this event, record it here.
|-
|timemodified
|int(10)
|time stamp of the last attempt to run this from the queue
|}
 
==Standards for naming events==
 
All event names should follow a consistent naming pattern, such as modulename_noun_verb
 
==Events which exist==
 
===Users===
* user_updated
* password_changed
 
===Courses===
* course_updated
* course_deleted
* category_updated
* category_deleted
 
===Groups===
* group_deleted
* grouping_deleted
* group_user_added
* group_user_removed
 
==Events wishlist==
 
List of events which it would be nice to have.  Please add to this list if what you want is not shown here.
 
* user_created (for example to handle custom emails.  this is commonly desired: e.g. send a custom email to a related person (teacher, boss, etc.) based on some institution-specific logic)
* user_enrolled_in_course
* user_unenrolled_from_course
* course_created


== See also ==
== See also ==


* [[Development:Grades]]
* [http://moodle.org/mod/forum/discuss.php?d=69103 General Developer Forum thread for discussing this proposal].
 
* [[:Development:Grades]]


[[Category:Developer]]
[[Category:Developer|Events]]
[[Category:Grades]]
[[Category:Grades]]

Latest revision as of 14:22, 10 October 2008

Moodle1.9


The Events API is a new core system in Moodle to allow better communication between modules. It's based on modules triggering new events with attached data, and the other modules handling those events with custom functions.

Overview

We'll be using the example of a grade being posted from a module into the new gradebook in Moodle 1.9, but there are obviously all kinds of events possible.

Triggering an event

Whenever a grade is created or changed by a module, it should “tell” the system about it (in addition to any local working storage it uses). So, using the quiz as an example, we first define an object as follows:

$eventdata = new object();
$eventdata->itemid = $grade_item->id;
$eventdata->userid = $USER->id;
$eventdata->gradevalue = $currentvalue;

Then we post the object as an event and forget about it:

events_trigger('grade_updated', $eventdata);

Handling an event

Modules can define an events.php in their db directory which defines events they want to be notified about, and describes which of their functions or class methods should be notified. For example, an export plugin could register something like:

$handlers = array (
    'grade_updated' => array (
        'handlerfile'      => '/grade/export/banner/lib.php',
        'handlerfunction'  => 'banner_handle_grade_test',    // argument to call_user_func(), could be an array
        'schedule'         => 'cron'
    ) 
);

These are parsed during install / upgrade and stored in a simple database table.

Then, when a grade_updated event happens, all the registered functions for that event will be called something like this (but with more error handling):

         include_once($CFG->dirroot.$handlers['grade_updated']['handlerfile']);
         call_user_func($handlers['grade_updated']['handlerfunction'], $eventdata);

All plugins in Moodle have access to this and can this easily “hook in” to 'grade_updated' events (and of course any other events).

Database structure

There are 3 core tables for events. Note that if a handler is queued, and yet to be processed or processing failed, then all subsequent calls on that handler must be queued.

events_handlers

This table is for storing which components requests what type of event, and the location of the responsible handlers. For example, the grade book can register 'grade_added' event with a function add_grade() that should be called any time an 'grade_added' event is triggered by a module.

These entries are created by parsing events.php files in all the modules, and can be rebuilt any time (during an upgrade, say).

Field Type Info
id int(10) auto increment identifier
eventname varchar(255) name of the event, e.g. 'grade_updated'
handlermodule varchar(255) e.g. moodle, mod/forum, block/rss_client
handlerfile varchar(255) path to the file of the function, eg /grade/export/lib.php
handlerfunction text serialized string or array describing function, suitable to be passed to call_user_func()
schedule varchar(255) 'cron' or 'instant'.
status int(10) number of failed attempts to process this handler

events_queue

This table is for storing queued events. It stores only one copy of the eventdata here, and entries from this table are being references by the events_queue_handlers table.

Field Type Info
id int(10) auto increment identifier
eventdata longtext serialized version of the data object passed to the event handler.
stackdump text serialized debug_backtrace showing where the event was fired from
userid int(10) $USER->id when the event was fired
timecreated int(10) time stamp of the first time this was added

events_queue_handlers

This is the list of queued handlers for processing. The event object is retrieved from the events_queue table. When no further reference is made to the events_queue table, the corresponding entry in the events_queue table should be deleted. Entry should get deleted (?) after a successful event processing by the specified handler. The status field keeps track of failures, after it gets to a certain number (eg 10?) it should trigger an "event failed" event (that could result in admin being emailed etc, or perhaps even the originating module taking care of it or rolling something back etc).

Field Type Info
id int(10) auto increment identifier
queuedeventid int(10) foreign key id corresponding to the id of the event_queues table
handlerid int(10) foreign key id corresponding to the id of the event_handlers table
status int(10) number of failed attempts to process this handler
errormessage text if an error happened last time we tried to process this event, record it here.
timemodified int(10) time stamp of the last attempt to run this from the queue

Standards for naming events

All event names should follow a consistent naming pattern, such as modulename_noun_verb

Events which exist

Users

  • user_updated
  • password_changed

Courses

  • course_updated
  • course_deleted
  • category_updated
  • category_deleted

Groups

  • group_deleted
  • grouping_deleted
  • group_user_added
  • group_user_removed

Events wishlist

List of events which it would be nice to have. Please add to this list if what you want is not shown here.

  • user_created (for example to handle custom emails. this is commonly desired: e.g. send a custom email to a related person (teacher, boss, etc.) based on some institution-specific logic)
  • user_enrolled_in_course
  • user_unenrolled_from_course
  • course_created

See also