Development:Events API: Difference between revisions
Brian King (talk | contribs) |
(Updated examples, removed obsolete tag) |
||
Line 1: | Line 1: | ||
{{Moodle 1.9}} | {{Moodle 1.9}} | ||
==Overview== | ==Overview== | ||
The Events API is a core system in Moodle to allow communication between modules. | |||
Modules can trigger new events with attached data, and other module can elect to handle those events with custom functions. | |||
==Example== | |||
Let's look at an example of how events are used to implement Messaging in Moodle 2.0. In the messaging system, textual messages are generated for users by different modules, and the user can decide how certain types of messages are displayed. | |||
===Triggering an event=== | ===Triggering an event=== | ||
When a messaging event occurs, the module should trigger a "message_send" event. In this example let's pretend someone just posted to a forum. | |||
The forum module needs to create an object with the data that this event needs. This may vary completely for different types of events, it's just a data object. | |||
$eventdata = new object(); | $eventdata = new object(); | ||
$eventdata-> | $eventdata->component = 'mod/forum'; // path in Moodle | ||
$eventdata-> | $eventdata->name = 'posts'; // type of message from that module (as module defines it) | ||
$eventdata-> | $eventdata->userfrom = $userfrom; // user object | ||
$eventdata->userto = $userto; // user object | |||
$eventdata->subject = $postsubject; // very short one-line subject | |||
$eventdata->fullmessage = $posttext; // raw text | |||
$eventdata->fullmessageformat = FORMAT_PLAIN; // text format | |||
$eventdata->fullmessagehtml = $posthtml; // html rendered version | |||
$eventdata->smallmessage = ''; // useful for plugins like sms or twitter | |||
Then we post the object as an event and forget about it: | Then we post the object as an event and forget about it: | ||
events_trigger(' | events_trigger('message_send', $eventdata); | ||
===Handling an event=== | ===Handling an event=== | ||
Modules can define an events.php in | Modules or core code can define an events.php in the db directory which defines events they want to be notified about, and describes which of their functions or class methods should be notified. For this case, there is this definition of a handler in lib/db/events.php | ||
$handlers = array ( | $handlers = array ( | ||
' | 'message_send' => array ( | ||
'handlerfile' => '/lib/messagelib.php', | |||
'handlerfunction' => 'message_send_handler', | |||
'schedule' => 'instant' | |||
) | |||
); | ); | ||
These events.php files are parsed during install / upgrade and stored in a simple database table. | |||
Now, when a '''message_send''' event happens, all the registered handlers functions for that event will be called something like this (but with more error handling): | |||
include_once($CFG->dirroot.$handlers['message_send']['handlerfile']); | |||
call_user_func($handlers['message_send']['handlerfunction'], $eventdata); | |||
Any code can hook into any events this way. | |||
==Database structure== | ==Database structure== | ||
Line 46: | Line 62: | ||
===events_handlers=== | ===events_handlers=== | ||
This table is for storing which components requests what type of event, and the location of the responsible | This table is for storing which components requests what type of event, and the location of the responsible handler functions. | ||
These entries are created by parsing events.php files in all the modules, and can be rebuilt any time (during an upgrade, say). | These entries are created by parsing events.php files in all the modules, and can be rebuilt any time (during an upgrade, say). | ||
Line 61: | Line 77: | ||
|eventname | |eventname | ||
|varchar(255) | |varchar(255) | ||
|name of the event, e.g. ' | |name of the event, e.g. 'message_send' | ||
|- | |- | ||
|handlermodule | |handlermodule | ||
Line 69: | Line 85: | ||
|handlerfile | |handlerfile | ||
|varchar(255) | |varchar(255) | ||
|path to the file of the function, eg / | |path to the file of the function, eg /lib/messagelib.php | ||
|- | |- | ||
|handlerfunction | |handlerfunction | ||
Line 182: | Line 198: | ||
* [http://moodle.org/mod/forum/discuss.php?d=69103 General Developer Forum thread for discussing this proposal]. | * [http://moodle.org/mod/forum/discuss.php?d=69103 General Developer Forum thread for discussing this proposal]. | ||
* [[ | * [[Development:Messaging_2.0]] | ||
[[Category:Developer|Events]] | [[Category:Developer|Events]] | ||
[[Category:Grades]] | [[Category:Grades]] |
Revision as of 02:08, 26 May 2009
Overview
The Events API is a core system in Moodle to allow communication between modules.
Modules can trigger new events with attached data, and other module can elect to handle those events with custom functions.
Example
Let's look at an example of how events are used to implement Messaging in Moodle 2.0. In the messaging system, textual messages are generated for users by different modules, and the user can decide how certain types of messages are displayed.
Triggering an event
When a messaging event occurs, the module should trigger a "message_send" event. In this example let's pretend someone just posted to a forum.
The forum module needs to create an object with the data that this event needs. This may vary completely for different types of events, it's just a data object.
$eventdata = new object(); $eventdata->component = 'mod/forum'; // path in Moodle $eventdata->name = 'posts'; // type of message from that module (as module defines it) $eventdata->userfrom = $userfrom; // user object $eventdata->userto = $userto; // user object $eventdata->subject = $postsubject; // very short one-line subject $eventdata->fullmessage = $posttext; // raw text $eventdata->fullmessageformat = FORMAT_PLAIN; // text format $eventdata->fullmessagehtml = $posthtml; // html rendered version $eventdata->smallmessage = ; // useful for plugins like sms or twitter
Then we post the object as an event and forget about it:
events_trigger('message_send', $eventdata);
Handling an event
Modules or core code can define an events.php in the db directory which defines events they want to be notified about, and describes which of their functions or class methods should be notified. For this case, there is this definition of a handler in lib/db/events.php
$handlers = array ( 'message_send' => array ( 'handlerfile' => '/lib/messagelib.php', 'handlerfunction' => 'message_send_handler', 'schedule' => 'instant' ) );
These events.php files are parsed during install / upgrade and stored in a simple database table.
Now, when a message_send event happens, all the registered handlers functions for that event will be called something like this (but with more error handling):
include_once($CFG->dirroot.$handlers['message_send']['handlerfile']); call_user_func($handlers['message_send']['handlerfunction'], $eventdata);
Any code can hook into any events this way.
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 handler functions.
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. 'message_send' |
handlermodule | varchar(255) | e.g. moodle, mod/forum, block/rss_client |
handlerfile | varchar(255) | path to the file of the function, eg /lib/messagelib.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_created
- 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