Note:

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

Migrating logging calls in plugins: Difference between revisions

From MoodleDocs
No edit summary
Line 149: Line 149:
<span id="add_record_snapshot">Record snapshot</a> can be added for any DB table related to the event. It MUST be exact record from the DB, with correct field types and without additional fields. Also you must add a record snapshot when you delete something from database. Record snapshot usually is not used by loggers but it may be used by observers.
<span id="add_record_snapshot">Record snapshot</a> can be added for any DB table related to the event. It MUST be exact record from the DB, with correct field types and without additional fields. Also you must add a record snapshot when you delete something from database. Record snapshot usually is not used by loggers but it may be used by observers.


Record snapshots should be added only when you already have an object do not need to perform any additional DB queries to retrieve it. Otherwise the record will be retieved by get_record_snapshot() automatically and only if needed.
Record snapshots should be added only when you already have an object do not need to perform any additional DB queries to retrieve it. Otherwise the record will be retieved by get_record_snapshot() automatically and only if needed. '''get_record_snapshot() can not be used inside event class''', if you need additional information for internal functions, add it to 'other'.


== Self-check ==
== Self-check ==


You may notice that the most of existing events in Moodle also have function validate_data() . You can also add it for your own safety to ensure that you don't forget to define all required data when triggering event. Also we highly recommend to cover your events with unittests. Search for files with the names events_test.php in Moodle for examples.
You may notice that the most of existing events in Moodle also have function validate_data() . You can also add it for your own safety to ensure that you don't forget to define all required data when triggering event. Also we highly recommend to cover your events with unittests. Search for files with the names events_test.php in Moodle for examples.

Revision as of 07:43, 21 February 2014

This document is aimed to assist developers in replacing existing add_to_log() calls in the plugin with the events. This can be implemented in Moodle 2.6 and this must be done in 2.7.

As a quick reminder: Event 2 was introduced in Moodle 2.6, new Logging 2 system is being introduced in Moodle 2.7. Function add_to_log() becomes deprecated. Log storage that uses the DB table log is now called "legacy". When replacing the add_to_log() with triggering of an event developer also must ensure that he also generates an entry to the legacy log. It will only be used if legacy log is enabled since it may be enabled on systems that use too many custom reports relying on presence of log table and it would take time to migrate the reports.

Quick guide

If you are replacing common add_to_log() calls such as "view" and "view all" in mod/XXX/view.php and mod/XXX/index.php, see below. Otherwise do the following:

Step 1. Choose a name for event

It should have syntax OBJECT_VERB, for example "entry_added", "work_submitted", etc. It does not need to have plugin name in it because it is obvious from namespace. See Event 2 for more details on events names.

Define language string for the event name in YOURPLUGINDIR/lang/en/FULLPLUGINNAME.php :

$string['eventSOMETHINGHAPPENED] = 'SOMETHING has HAPPENED';

Step 2. Create event class

It must be located in YOURPLUGINDIR/classes/event/SOMETHING_HAPPENED.php , typical example:

namespace FULLPLUGINNAME\event;
defined('MOODLE_INTERNAL') || die();
class SOMETHING_HAPPENED extends \core\event\base {
    protected function init() {
        $this->data['crud'] = 'c'; // c(reate), r(ead), u(pdate), d(elete)
        $this->data['edulevel'] = self::LEVEL_PARTICIPATING;
        $this->data['objecttable'] = '...';
    }

    public static function get_name() {
        return get_string('eventSOMETHINGHAPPENED', 'FULLPLUGINNAME');
    }

    public function get_description() {
        return "User {$this->userid} has ... ... ... with id {$this->objectid}.";
    }

    public function get_url() {
        return new \moodle_url('....', array());
    }

    public function get_legacy_log_data() {
        return array($this->courseid, 'PLUGINNAME', 'LOGACTION',
            '...........',
            $this->objectid, $this->contextinstanceid);
    }
}

Step 3. Trigger event instead of add_to_log()

Replace add_to_log() with triggering of event. This is a common example for event inside an activity module:

add_to_log($course->id, 'PLUGINNAME', 'LOGACTION', '...........', $objid, $cmid);

becomes:

$event = \FULLPLUGINNAME\event\SOMETHING_HAPPENED::create(array(
    'objectid' => $objid,
    'context' => context_module::instance($cmid)
));
$event->trigger();

Replacing 'view' event in the modules

This is usually found in mod/PLUGINNAME/view.php (or in lib function included from this file) and indicates that user viewed the module.

Step 1. Choosing the name

The name is already choosen - course_module_viewed - and the language string is defined in core.

Step 2. Defining class

YOURPLUGINDIR/classes/event/course_module_viewed.php :

namespace FULLPLUGINNAME\event;
defined('MOODLE_INTERNAL') || die();
class course_module_viewed extends \core\event\course_module_viewed {
    protected function init() {
        $this->data['objecttable'] = 'PLUGINNAME';
        parent::init();
    }
    // You might need to overwrite get_url() and get_legacy_log_data() if view mode needs to be stored as well.
}

Step 3. Triggering event

This example takes data from $PAGE object but you may as well substite with ids and objects that you fetched:

$event = \FULLPLUGINNAME\event\course_module_viewed::create(array(
    'objectid' => $PAGE->cm->instance,
    'context' => $PAGE->context,
));
$event->add_record_snapshot('course', $PAGE->course);
$event->add_record_snapshot($PAGE->cm->modname, $activityrecord); // You can use $PAGE->activityrecord if you have set it or skip this line if you don't have a record.
$event->trigger();

Replacing 'view all' event in the modules

This is usually found in mod/PLUGINNAME/index.php (or in lib function included from this file) and indicates that user viewed list of modules of this type in the course.

Step 1. Choosing the name

The name is already choosen - course_module_instance_list_viewed - and the language string is defined in core.

Step 2. Defining class

YOURPLUGINDIR/classes/event/course_module_instance_list_viewed.php :

namespace FULLPLUGINNAME\event;
defined('MOODLE_INTERNAL') || die();
class course_module_instance_list_viewed extends \core\event\course_module_instance_list_viewed {
}

Step 3. Triggering event

$event = \FULLPLUGINNAME\event\course_module_instance_list_viewed::create(array(
    'context' => context_course::instance($course->id)
));
$event->trigger();

Information stored in event

Event usually represents the change in one record of one table. This is what fields 'objecttable' and 'objectid' refer to. 'userid' will be taken from $USER, 'courseid' will be automatically taken from context.

Very often event involves action performed by one user in relation to another (i.e. grading), in this case you can fill 'relateduserid' when triggering event.

All additional information that you want to be logged you may store in 'other' field (this is an associative array). Use those fields in get_description(), get_url(), get_legacy_data(), etc.

Do NOT use $this->context inside an event class! Remember that functions get_description() and get_url() may be called on events restored from log. It is possible that the original context does not exist any more. Instead use $this->contextid, $this->contextlevel, $this->contextinstanceid.

See the full list in Event_2#Information_contained_in_events

Function init()

Add here all information that is static for this event, such as 'objecttable', 'crud', 'edulevel', etc.

Function add_record_snapshot()

Record snapshot</a> can be added for any DB table related to the event. It MUST be exact record from the DB, with correct field types and without additional fields. Also you must add a record snapshot when you delete something from database. Record snapshot usually is not used by loggers but it may be used by observers.

Record snapshots should be added only when you already have an object do not need to perform any additional DB queries to retrieve it. Otherwise the record will be retieved by get_record_snapshot() automatically and only if needed. get_record_snapshot() can not be used inside event class, if you need additional information for internal functions, add it to 'other'.

Self-check

You may notice that the most of existing events in Moodle also have function validate_data() . You can also add it for your own safety to ensure that you don't forget to define all required data when triggering event. Also we highly recommend to cover your events with unittests. Search for files with the names events_test.php in Moodle for examples.