if (!empty($cachedevents[$eventname])) {
if ($cachedevents[$eventname] == $fileevent) {
unset($cachedevents[$eventname]);
- continue; // breaks the cachedevents loop
+ continue; // breaks the cachedevents loop
}
}
// if we are here, no break is called, file event is new
return $deletecount;
}
+/****************** End of Events handler Definition code *******************/
+
+
+/**
+ * puts a handler on queue
+ * @param object handler - event handler object from db
+ * @param object eventdata - event data object
+ * @param bool failed - whether this handler is queued because of a failed event trigger
+ * @return
+ */
+function queue_handler($handler, $eventdata, $failed=false) {
+ global $USER;
+ // adds a record to events_queue (if not exist)
+ if (!$existing_event = get_record('events_queue', 'eventdata', serialize($eventdata))) {
+ // add it
+ $eq = new object;
+ $eq->userid = $USER->id;
+ $eq->schedule = $eventdata->schedule;
+ $eq->eventdata = serialize($eventdata);
+ $eq->stackdump = '';
+ $eq->timecreated = time();
+ $eventid = insert_record('events_queue', $eq);
+ } else {
+ $eventid = $existing_event->id;
+ }
+
+ // check if this event handler is already queued
+ if (!$qh = get_record('events_queue_handlers', 'queuedeventid', $eventid, 'handlerid', $handler->id)) {
+ // make a new one
+ $qh = new object;
+ $qh->queuedeventid = $eventid;
+ $qh->handlerid = $handler->id;
+ $qh->status = 0;
+ $qh->errormessage = '';
+ $qh->timemodified = time();
+ return insert_record('events_queue_handlers', $qh);
+ } else {
+ // update existing one, failed again
+ $qh->states++;
+ $qh->timemodified = time();
+ update_record('events_queue_handlers', $qh);
+ return -1; // failed
+ }
+}
+
+/**
+ * function to call all eventhandlers when triggering an event
+ * @param eventname - name of the event
+ * @param eventdata - event data object
+ * @return number of failed events
+ */
+function trigger_events($eventname, $eventdata) {
+ $failedevent = 0; // number of failed events.
+ // pull out all registered event handlers
+ if ($handlers = get_records('events_handlers', 'eventname', $eventname)) {
+ foreach ($handlers as $handler) {
+ // either excute it now
+
+ // if event type is
+ if ($eventdata->schedule == "instant") {
+ if (trigger_event($handler, $eventdata)) {
+ continue;
+ } else {
+ // update the failed flag
+ $failed = true;
+ $failedevent ++;
+ }
+ }
+ // if even type is not instant, or trigger failed, queue it
+ $queuedevent++;
+ queue_handler($handler, $eventdata, $failed);
+ }
+ }
+ return $failedevent;
+}
+
+/**
+ * trigger a single event with a specified handler
+ * @param handler - hander object from db
+ * @param eventdata - event dataobject
+ * @return bool - success or fail
+ */
+function trigger_event($handler, $eventdata) {
+
+ global $CFG;
+ // checks for handler validity
+
+ // check if the same handler is queued already, if so, return false so we can queue it
+ // TODO
+
+ include_once($CFG->dirroot.$handler->handlerfile);
+ return call_user_func($handler->handlerfunction, $eventdata);
+}
+
+/**
+ * given a queued handler, call the respective event handler to process the event
+ * @input object handler- events_queued_handler object from db
+ * @return fail or custom function value
+ */
+function events_process_queued_handler($handler) {
+ // checks for handler validity
+ global $CFG;
+
+ // get handler
+ if (!$eventhandler = get_record('events_handlers', 'id', $handler->handlerid)) {
+ // can't proceed with no handler
+ return false;
+ }
+ // get event object
+ if (!$eventobject = get_record('events_queue', 'id', $handler->queuedeventid)) {
+ // can't proceed with no event object
+ return false;
+ }
+ // call the function sepcified by the handler
+
+ return trigger_event($eventhandler, unserialize($eventobject->eventdata));
+}
+
+/**
+ * Events cron will try to empty the events queue by processing all the queued events handlers
+ */
+function events_cron() {
+
+ global $CFG;
+
+ if ($handlers = get_records_select('events_queue_handlers', '', 'timemodified')) {
+ foreach ($handlers as $handler) {
+ if (events_process_queued_handler($handler)) {
+ // dequeue();
+ events_dequeue($handler);
+ } else {
+ // failed again, put back on queue
+ $handler->timemodified = time();
+ $handler->status++;
+ update_record('events_queue_handlers', $handler);
+ }
+ }
+ }
+}
+
+/**
+ * removes this queued handler from the events_queued_handler table
+ * removes events_queue record from events_queue if no more references to this event object exists
+ * @input object handler - events_queued_handler object from db
+ */
+function events_dequeue($handler) {
+
+ if (delete_records('events_queue_handlers', 'id', $handler->id)) {
+ // if no more queued handler is pointing to the same event
+ if (!record_exists('events_queue_handlers', 'queuedeventid', $handler->queuedeventid)) {
+ delete_records('events_queue', 'id', $handler->queuedeventid);
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
?>
\ No newline at end of file
--- /dev/null
+<?php
+
+/** $Id */
+require_once(dirname(__FILE__) . '/../../config.php');
+
+global $CFG;
+require_once($CFG->libdir . '/simpletestlib.php');
+require_once($CFG->libdir . '/eventslib.php');
+require_once($CFG->libdir . '/dmllib.php');
+
+// dummy test function
+function plusone($eventdata) {
+ return $eventdata->data+1;
+}
+
+class eventslib_test extends UnitTestCase {
+
+ var $handlerid;
+ var $handler;
+ var $storedhandler;
+ /**
+ * Create temporary entries in the database for these tests.
+ * These tests have to work no matter the data currently in the database
+ * (meaning they should run on a brand new site). This means several items of
+ * data have to be artificially inseminated (:-) in the DB.
+ */
+ function setUp() {
+
+ global $CFG;
+
+ // make a dummy event
+ $eventhandler -> eventname = 'testevent';
+ $eventhandler -> handlermodule = 'unittext';
+ $eventhandler -> handlerfile = '/lib/simpletest/testeventslib.php';
+ $eventhandler -> handlerfunction = 'plusone';
+
+ $this -> handler = $eventhandler;
+ $this -> handlerid = insert_record('events_handlers', $eventhandler);
+ $this -> handler->id = $this->handlerid;
+
+ }
+
+ /**
+ * Delete temporary entries from the database
+ */
+ function tearDown()
+ {
+ delete_records('events_handlers', 'id', $this->handlerid);
+ }
+
+ /**
+ * tests queue_handler() and events_process_queued_handler() and trigger_event()
+ */
+ function test_events_process_queued_handler_handler() {
+
+ $eventdata = new object;
+ $eventdata->data = 1;
+ $eventdata->schedule = 'instant';
+ $id = queue_handler($this->handler, $eventdata);
+ $storedhandler = get_record('events_queue_handlers', 'id', $id);
+ $retval = events_process_queued_handler($storedhandler);
+ $this->assertEqual(2, $retval);
+ $this->storedhandler = $storedhandler;
+ }
+
+ /**
+ * tests events_dequeue()
+ */
+ function test_events_dequeue() {
+ $this->assertTrue(events_dequeue($this->storedhandler));
+ }
+
+ /**
+ * tests trigger_events funtion()
+ */
+ function test_trigger_events() {
+ $eventdata = new object;
+ $eventdata->data = 2;
+ $eventdata->schedule = 'instant';
+ $this->assertEqual(0, trigger_events('testevent', $eventdata));
+ }
+}
+
+?>
\ No newline at end of file